Skip to content

Add Hgi functions to get and set default backend #3604

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

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
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
117 changes: 78 additions & 39 deletions pxr/imaging/hgi/hgi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ TF_REGISTRY_FUNCTION(TfType)
TfType::Define<Hgi>();
}

TfToken Hgi::_defaultHgiToken;

Hgi::Hgi()
: _uniqueIdCounter(1)
{
Expand All @@ -42,41 +44,71 @@ Hgi::SubmitCmds(HgiCmds* cmds, HgiSubmitWaitType wait)
}
}

static Hgi*
_MakeNewPlatformDefaultHgi()
static TfToken
_PlatformDefaultHgiToken()
{
TF_DEBUG(HGI_DEBUG_INSTANCE_CREATION).Msg("Attempting to create platform "
"default Hgi\n");

// We use the plugin system to construct derived Hgi classes to avoid any
// linker complications.

PlugRegistry& plugReg = PlugRegistry::GetInstance();

const char* hgiType =
TfToken hgiToken =
#if defined(ARCH_OS_LINUX)
"HgiGL";
HgiTokens->OpenGL;
#elif defined(ARCH_OS_DARWIN)
"HgiMetal";
HgiTokens->Metal;
#elif defined(ARCH_OS_WINDOWS)
"HgiGL";
HgiTokens->OpenGL;
#else
"";
TfToken();
#error Unknown Platform
return nullptr;
#endif

if (TfGetEnvSetting(HGI_ENABLE_VULKAN)) {
#if defined(PXR_VULKAN_SUPPORT_ENABLED)
hgiType = "HgiVulkan";
hgiToken = HgiTokens->Vulkan;
#else
TF_CODING_ERROR(
"Build requires PXR_VULKAN_SUPPORT_ENABLED=true to use Vulkan");
#endif
}

return hgiToken;
}

static std::string
_HgiTokenToType(const TfToken& hgiToken)
{
if (hgiToken == HgiTokens->OpenGL) {
#if defined(PXR_GL_SUPPORT_ENABLED)
return "HgiGL";
#endif
} else if (hgiToken == HgiTokens->Vulkan) {
#if defined(PXR_VULKAN_SUPPORT_ENABLED)
return "HgiVulkan";
#endif
} else if (hgiToken == HgiTokens->Metal) {
#if defined(PXR_METAL_SUPPORT_ENABLED)
return "HgiMetal";
}
#endif

return "";
}

static Hgi*
_MakeNewPlatformDefaultHgi(const TfToken& defaultHgiToken)
{
TF_DEBUG(HGI_DEBUG_INSTANCE_CREATION).Msg("Attempting to create platform "
"default Hgi\n");

// We use the plugin system to construct derived Hgi classes to avoid any
// linker complications.

PlugRegistry& plugReg = PlugRegistry::GetInstance();

const TfToken hgiToken = defaultHgiToken.IsEmpty() ?
_PlatformDefaultHgiToken() : defaultHgiToken;
const std::string hgiType = _HgiTokenToType(hgiToken);

TF_DEBUG(HGI_DEBUG_INSTANCE_CREATION).Msg("Platform default Hgi: "
"%s\n", hgiType);
"%s\n", hgiType.c_str());

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

Expand Down Expand Up @@ -104,7 +136,7 @@ _MakeNewPlatformDefaultHgi()

if (!instance->IsBackendSupported()) {
TF_DEBUG(HGI_DEBUG_INSTANCE_CREATION).Msg("Hgi %s is not supported\n",
hgiType);
hgiType.c_str());
// XXX Currently, returning nullptr (rather than a non-supported hgi
// instance) causes a crash in one of our studio tests. We disable the
// desired behavior until we can fix the test.
Expand All @@ -114,34 +146,23 @@ _MakeNewPlatformDefaultHgi()
}

TF_DEBUG(HGI_DEBUG_INSTANCE_CREATION).Msg("Successfully created platform "
"default Hgi %s\n", hgiType);
"default Hgi %s\n", hgiType.c_str());

return instance;
}

static Hgi*
_MakeNamedHgi(const TfToken& hgiToken)
_MakeNamedHgi(const TfToken& hgiToken, const TfToken& defaultHgiToken)
{
TF_DEBUG(HGI_DEBUG_INSTANCE_CREATION).Msg("Attempting to create named Hgi "
"%s\n", hgiToken.GetText());

std::string hgiType;
if (hgiToken.IsEmpty()) {
return _MakeNewPlatformDefaultHgi(defaultHgiToken);
}

if (hgiToken == HgiTokens->OpenGL) {
#if defined(PXR_GL_SUPPORT_ENABLED)
hgiType = "HgiGL";
#endif
} else if (hgiToken == HgiTokens->Vulkan) {
#if defined(PXR_VULKAN_SUPPORT_ENABLED)
hgiType = "HgiVulkan";
#endif
} else if (hgiToken == HgiTokens->Metal) {
#if defined(PXR_METAL_SUPPORT_ENABLED)
hgiType = "HgiMetal";
#endif
} else if (hgiToken.IsEmpty()) {
return _MakeNewPlatformDefaultHgi();
} else {
const std::string hgiType = _HgiTokenToType(hgiToken);
if (hgiType.empty()) {
// If an invalid token is provided, return nullptr.
TF_CODING_ERROR("Unsupported token %s was provided.",
hgiToken.GetText());
Expand Down Expand Up @@ -201,19 +222,19 @@ Hgi::GetPlatformDefaultHgi()
TF_WARN("GetPlatformDefaultHgi is deprecated. "
"Please use CreatePlatformDefaultHgi");

return _MakeNewPlatformDefaultHgi();
return _MakeNewPlatformDefaultHgi(_defaultHgiToken);
}

HgiUniquePtr
Hgi::CreatePlatformDefaultHgi()
{
return HgiUniquePtr(_MakeNewPlatformDefaultHgi());
return HgiUniquePtr(_MakeNewPlatformDefaultHgi(_defaultHgiToken));
}

HgiUniquePtr
Hgi::CreateNamedHgi(const TfToken& hgiToken)
{
return HgiUniquePtr(_MakeNamedHgi(hgiToken));
return HgiUniquePtr(_MakeNamedHgi(hgiToken, _defaultHgiToken));
}

bool
Expand All @@ -239,6 +260,24 @@ Hgi::IsSupported(const TfToken& hgiToken)
return false;
}

bool
Hgi::SetPlatformDefaultBackend(const TfToken& hgiToken)
{
if (_HgiTokenToType(hgiToken).empty()) {
return false;
}

_defaultHgiToken = hgiToken;
return true;
}

TfToken
Hgi::GetPlatformDefaultBackend()
{
return _defaultHgiToken.IsEmpty() ? _PlatformDefaultHgiToken() :
_defaultHgiToken;
}

uint64_t
Hgi::GetUniqueId()
{
Expand Down
15 changes: 15 additions & 0 deletions pxr/imaging/hgi/hgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,20 @@ class Hgi
HGI_API
static bool IsSupported(const TfToken& hgiToken = TfToken());

/// Set the default backend that will be created by CreatePlatformDefaultHgi.
/// This may be set by the host application on startup, to communicate its
/// preferred backend to plugins.
/// If the OpenUSD was built without supported for the specified backend,
/// this returns false and the default backend is unchanged.
/// Thread safety: Not thread safe.
HGI_API
static bool SetPlatformDefaultBackend(const TfToken& hgiToken);

/// Get the default backend that will be created by CreatePlatformDefaultHgi.
/// Thread safety: This call is thread safe.
HGI_API
static TfToken GetPlatformDefaultBackend();

/// Returns a GraphicsCmds object (for temporary use) that is ready to
/// record draw commands. GraphicsCmds is a lightweight object that
/// should be re-acquired each frame (don't hold onto it after EndEncoding).
Expand Down Expand Up @@ -342,6 +356,7 @@ class Hgi
Hgi(const Hgi&) = delete;

std::atomic<uint64_t> _uniqueIdCounter;
static TfToken _defaultHgiToken;
};


Expand Down