diff --git a/lib/usd/ui/renderSetup/CMakeLists.txt b/lib/usd/ui/renderSetup/CMakeLists.txt index 5ef42945e1..8e06ef15ed 100644 --- a/lib/usd/ui/renderSetup/CMakeLists.txt +++ b/lib/usd/ui/renderSetup/CMakeLists.txt @@ -1,20 +1,4 @@ -# -# Copyright 2026 Autodesk -# -# 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 -# -# http://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. -# - add_subdirectory(rendering) target_sources(${PROJECT_NAME} diff --git a/lib/usd/ui/renderSetup/mayaRendererProvider.cpp b/lib/usd/ui/renderSetup/mayaRendererProvider.cpp index 8f99a01a29..3c517f43c0 100644 --- a/lib/usd/ui/renderSetup/mayaRendererProvider.cpp +++ b/lib/usd/ui/renderSetup/mayaRendererProvider.cpp @@ -16,55 +16,46 @@ #include "mayaRendererProvider.h" +#ifdef MAYA_HAS_USD_SETTINGS_NODES +#include +#endif + +#include +#include +#include + #include +#include #include +#include +#include +#include #include #include namespace MayaUsdRenderSetup { namespace { + //! \return the label Maya's own Render Settings dialog shows for `rendererName`. MString rendererUIName(const MString& rendererName) { MString cmd; cmd.format("renderer -query -rendererUIName \"^1s\"", rendererName); - MString uiName; - MGlobal::executeCommand(cmd, uiName); - return uiName; -} -} // namespace -std::vector MayaRendererProvider::availableRenderers() const -{ - MStringArray allRenderers; - MStatus status - = MGlobal::executeCommand("renderer -query -namesOfAvailableRenderers", allRenderers); - if (!status) { - MGlobal::displayWarning("Unable to retrieve available renderers."); - return {}; - } + MString uiName; + MStatus status = MGlobal::executeCommand(cmd, uiName); + if (status != MS::kSuccess) + return rendererName; - std::vector renderers; - renderers.reserve(allRenderers.length()); - for (const auto& rendererName : allRenderers) { - AdskUsdRenderSetup::RendererInfo info; - info.name = rendererName.asChar(); - info.displayName = rendererUIName(rendererName).asChar(); - info.isHydra = isHydraCapable(info.name); - renderers.push_back(info); - } - return renderers; -} + if (uiName.length() == 0) + return rendererName; -std::string MayaRendererProvider::currentRenderer() const -{ - MString result; - MGlobal::executeCommand("currentRenderer()", result); - return result.asChar(); + return uiName; } -bool MayaRendererProvider::isHydraCapable(const std::string& rendererName) const +//! \return true if the named renderer is capable of rendering through Hydra. +bool isHydraCapable(const std::string& rendererName) { MString cmd; cmd.format("renderer -query -capability \"isHydra\" \"^1s\"", MString(rendererName.c_str())); @@ -80,18 +71,213 @@ bool MayaRendererProvider::isHydraCapable(const std::string& rendererName) const return false; } - switch (result.resultType()) { - case MCommandResult::kString: { - MString value; - result.getResult(value); - return value == "true" || value == "1"; + if (result.resultType() != MCommandResult::kString) + return false; + + MString value; + result.getResult(value); + return value == "true" || value == "1"; +} + +//! \brief RAII wrapper for HdRendererPlugin pointers. +class RendererPluginPointer +{ +public: + RendererPluginPointer( + PXR_NS::HdRendererPluginRegistry& registry, + const PXR_NS::TfToken& rendererId) + : _registry(registry) + , _plugin(registry.GetRendererPlugin(rendererId)) + { + } + + ~RendererPluginPointer() + { + if (_plugin) { + _registry.ReleasePlugin(_plugin); + } + } + + PXR_NS::HdRendererPlugin* get() const { return _plugin; } + +private: + PXR_NS::HdRendererPluginRegistry& _registry; + PXR_NS::HdRendererPlugin* _plugin; +}; + +//! \brief RAII wrapper for HdRenderDelegate pointers. +class RenderDelegatePointer +{ +public: + RenderDelegatePointer(PXR_NS::HdRendererPlugin* plugin) + : _plugin(plugin) + , _delegate(plugin ? plugin->CreateRenderDelegate() : nullptr) + { + } + + ~RenderDelegatePointer() + { + if (_plugin && _delegate) { + _plugin->DeleteRenderDelegate(_delegate); + } } - default: return false; + + PXR_NS::HdRenderDelegate* get() const { return _delegate; } + +private: + PXR_NS::HdRendererPlugin* _plugin; + PXR_NS::HdRenderDelegate* _delegate; +}; + +//! \return true if the named renderer is available and capable of rendering through Hydra. +bool isHydraRendererAvailable( + PXR_NS::HdRendererPluginRegistry& registry, + const PXR_NS::TfToken& rendererId) +{ + RendererPluginPointer plugin(registry, rendererId); + if (!plugin.get()) + return false; + + // As of 22.02, this needs to be called for Storm + if (rendererId == PXR_NS::TfToken("HdStormRendererPlugin")) { + PXR_NS::GlfContextCaps::InitInstance(); } + + if (!plugin.get()->IsSupported()) + return false; + + RenderDelegatePointer delegate(plugin.get()); + if (!delegate.get()) + return false; + + return true; +} + +//! \return a map of every renderer Maya currently knows about, Hydra-capable or not. +std::map getRenderersMap() +{ + std::map renderers; + + { + MStringArray mayaRenderers; + MStatus status + = MGlobal::executeCommand("renderer -query -namesOfAvailableRenderers", mayaRenderers); + if (!status) { + MGlobal::displayWarning("Unable to retrieve available renderers."); + } else { + for (const auto& rendererName : mayaRenderers) { + AdskUsdRenderSetup::RendererInfo info; + info.name = rendererName.asChar(); + info.displayName = rendererUIName(rendererName).asChar(); + info.isHydra = isHydraCapable(info.name); + renderers[info.name] = std::move(info); + } + } + } + + { + PXR_NS::HdRendererPluginRegistry& registry + = PXR_NS::HdRendererPluginRegistry::GetInstance(); + std::vector hydraDescs; + registry.GetPluginDescs(&hydraDescs); + + for (const auto& desc : hydraDescs) { + const PXR_NS::TfToken rendererId = desc.id; + if (!isHydraRendererAvailable(registry, rendererId)) { + continue; + } + + // Note: some Hydra renderers may also be registered in Maya's legacy renderer registry, + // so we need to merge the two lists. + // + // The display-name registered with Maya is usually better than the one registered + // with Hydra, so we prefer that one if it exists. In that case we only update the + // isHydra flag, since the `isHydraCapable` query might not be reliable for some + // renderers. + const std::string name = rendererId.GetText(); + auto it = renderers.find(name); + if (it != renderers.end()) { + it->second.isHydra = true; + } else { + renderers[name] = AdskUsdRenderSetup::RendererInfo { name, desc.displayName, true }; + } + } + } + + return renderers; +} + +} // namespace + +std::vector MayaRendererProvider::availableRenderers() const +{ + std::vector renderers; + + auto renderersMap = getRenderersMap(); + renderers.reserve(renderersMap.size()); + for (const auto& pair : renderersMap) { + renderers.push_back(pair.second); + } + + return renderers; +} + +std::string MayaRendererProvider::currentRenderer() const +{ + MSelectionList slist; + slist.add("defaultRenderGlobals"); + MObject defaultRenderGlobalsObj; + if (slist.length() > 0 && slist.getDependNode(0, defaultRenderGlobalsObj)) { + MFnDependencyNode depNode(defaultRenderGlobalsObj); + MPlug currentRendererPlug = depNode.findPlug("currentRenderer", false); + if (!currentRendererPlug.isNull()) { + MString value; + currentRendererPlug.getValue(value); + if (value.length() > 0) { + return value.asChar(); + } + } + } + +#ifdef MAYA_HAS_USD_SETTINGS_NODES + std::string hydraRenderer = MAYAUSD_NS_DEF::SceneRenderDescription::getCurrentRenderer(); + if (!hydraRenderer.empty()) { + return hydraRenderer; + } +#endif + + return std::string(); } void MayaRendererProvider::switchRenderer(const std::string& next) { + // TODO: should we allow setting an empty renderer? + if (next.empty()) { + return; + } + + // This validates that the renderer is available and avoid + // using some arbitrary string in the MEL command. + { + const auto avail = getRenderersMap(); + const auto it = avail.find(next); + if (it == avail.end()) + return; + +#ifdef MAYA_HAS_USD_SETTINGS_NODES + if (it->second.isHydra) { + MAYAUSD_NS_DEF::SceneRenderDescription::setCurrentRenderer(next); + } else { + // TODO: do we need to clear the SceneRenderDescription current renderer when the + // renderer is switched to a legacy renderer? + MAYAUSD_NS_DEF::SceneRenderDescription::setCurrentRenderer(""); + } +#endif + } + + // Note: other code watch the "currentRenderer" attribute of the defaultRenderGlobals node, + // so we change it last after we already updated the `SceneRenderDescription` current + // renderer. MString cmd; cmd.format("setCurrentRenderer(\"^1s\")", MString(next.c_str())); MGlobal::executeCommand(cmd); diff --git a/lib/usd/ui/renderSetup/mayaRendererProvider.h b/lib/usd/ui/renderSetup/mayaRendererProvider.h index f09a374455..0e691eb5f2 100644 --- a/lib/usd/ui/renderSetup/mayaRendererProvider.h +++ b/lib/usd/ui/renderSetup/mayaRendererProvider.h @@ -17,14 +17,28 @@ #ifndef MAYAUSDUI_USD_RENDERSETUP_MAYARENDERERPROVIDER_H #define MAYAUSDUI_USD_RENDERSETUP_MAYARENDERERPROVIDER_H +#include + #include +#include +#include + namespace MayaUsdRenderSetup { //! MayaUSD implementation of AdskUsdRenderSetup::IRendererProvider for the Render Setup UI. -//! Lists every renderer Maya knows about and reads/writes Maya's global current renderer -//! (defaultRenderGlobals.currentRenderer). -class MayaRendererProvider : public AdskUsdRenderSetup::IRendererProvider +//! Reports available renderers from Maya's legacy renderer registry (mayaSoftware, arnold, etc., +//! marked isHydra=false) and from Hydra's HdRendererPluginRegistry (marked isHydra=true). +//! Reads and writes the current renderer from the appropriate store: +//! - Hydra renderers: UsdSettingsNode::currentRenderer attribute +//! - Legacy renderers: defaultRenderGlobals.currentRenderer attribute +#if defined(_MSC_VER) +// AdskUsdRenderSetup::IRendererProvider is a header-only interface (all its methods are +// inline), so it needs no dll-interface of its own for MayaRendererProvider to export safely. +#pragma warning(push) +#pragma warning(disable : 4275) +#endif +class MAYAUSD_UI_PUBLIC MayaRendererProvider : public AdskUsdRenderSetup::IRendererProvider { public: //! \return every renderer Maya currently knows about, Hydra-capable or not. @@ -34,13 +48,16 @@ class MayaRendererProvider : public AdskUsdRenderSetup::IRendererProvider std::string currentRenderer() const override; protected: - //! Switches Maya's current renderer via the setCurrentRenderer MEL proc. + //! Requests a switch to the named renderer. Leaves currentRenderer() unchanged + //! (and thus switchRenderer is implicitly declined) if the name is unknown. + //! For Hydra renderers: writes UsdSettingsNode::currentRenderer. + //! For legacy renderers: writes defaultRenderGlobals.currentRenderer and clears + //! UsdSettingsNode. void switchRenderer(const std::string& next) override; - -private: - //! \return true if `rendererName` reports the "isHydra" capability. - bool isHydraCapable(const std::string& rendererName) const; }; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif } // namespace MayaUsdRenderSetup diff --git a/test/lib/usd/CMakeLists.txt b/test/lib/usd/CMakeLists.txt index a583b09f8f..e27dba5d0b 100644 --- a/test/lib/usd/CMakeLists.txt +++ b/test/lib/usd/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(plugin) add_subdirectory(pxrUsdPreviewSurface) add_subdirectory(schemas) +add_subdirectory(ui) add_subdirectory(utils) add_subdirectory(translators) diff --git a/test/lib/usd/ui/CMakeLists.txt b/test/lib/usd/ui/CMakeLists.txt new file mode 100644 index 0000000000..9450ad30aa --- /dev/null +++ b/test/lib/usd/ui/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Copyright 2026 Autodesk +# +# 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 +# +# http://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. +# + +if (AdskUsdRenderSetup_FOUND) + add_subdirectory(renderSetup) +endif() diff --git a/test/lib/usd/ui/renderSetup/CMakeLists.txt b/test/lib/usd/ui/renderSetup/CMakeLists.txt new file mode 100644 index 0000000000..ee14bfec45 --- /dev/null +++ b/test/lib/usd/ui/renderSetup/CMakeLists.txt @@ -0,0 +1,42 @@ +# ----------------------------------------------------------------------------- +# C++ unit tests +# +# MayaRendererProvider talks to a live Maya session (MEL "renderer" queries, +# defaultRenderGlobals) and to USD's Hydra plugin registry, so this test +# brings up Maya in library ("standalone") mode itself (see main.cpp) rather +# than relying on Python's maya.standalone, which the other C++ tests under +# test/lib/mayaUsd/utils don't need. +# ----------------------------------------------------------------------------- +if(MAYA_HAS_USD_SETTINGS_NODES AND NOT IS_MACOSX) + add_executable(testMayaRendererProvider) + + target_sources(testMayaRendererProvider + PRIVATE + main.cpp + testMayaRendererProvider.cpp + ) + + mayaUsd_compile_config(testMayaRendererProvider) + + target_include_directories(testMayaRendererProvider + PRIVATE + ${ADSK_USD_RENDER_SETUP_INCLUDE_DIR} + ) + + target_link_libraries(testMayaRendererProvider + PRIVATE + GTest::GTest + ${MAYA_LIBRARIES} + mayaUsd + mayaUsdUI + ) + + mayaUsd_add_test(testMayaRendererProvider + COMMAND $ + ENV + "LD_LIBRARY_PATH=${ADDITIONAL_LD_LIBRARY_PATH}" + "MAYA_LOCATION=${MAYA_LOCATION}" + ) + + set_property(TEST testMayaRendererProvider APPEND PROPERTY LABELS SharedComponents) +endif() diff --git a/test/lib/usd/ui/renderSetup/main.cpp b/test/lib/usd/ui/renderSetup/main.cpp new file mode 100644 index 0000000000..58c648fc92 --- /dev/null +++ b/test/lib/usd/ui/renderSetup/main.cpp @@ -0,0 +1,51 @@ +// +// Copyright 2026 Autodesk +// +// 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 +// +// http://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. +// + +// MayaRendererProvider issues MEL "renderer" queries and looks up +// defaultRenderGlobals, so (unlike the other C++ unit tests under +// test/lib/mayaUsd/utils) this test executable needs a real Maya session. +// Bring one up in library mode before handing control to gtest. + +#include +#include + +#include + +#include + +int main(int argc, char** argv) +{ + MStatus status = MLibrary::initialize(argv[0], /*useBatchLicense*/ true); + if (!status) { + status.perror("MLibrary::initialize"); + return 1; + } + + // Registers UsdSettingsNode/UsdDefaultRenderDescription (used by + // MayaRendererProvider's Hydra-side currentRenderer()/switchRenderer()) + // and the setCurrentRenderer MEL proc that switchRenderer() invokes. + if (!MGlobal::executeCommand("loadPlugin \"mayaUsdPlugin\"")) { + fprintf(stderr, "Failed to load mayaUsdPlugin.\n"); + MLibrary::cleanup(1); + return 1; + } + + ::testing::InitGoogleTest(&argc, argv); + int result = RUN_ALL_TESTS(); + + MLibrary::cleanup(result); + return result; +} diff --git a/test/lib/usd/ui/renderSetup/testMayaRendererProvider.cpp b/test/lib/usd/ui/renderSetup/testMayaRendererProvider.cpp new file mode 100644 index 0000000000..096bf71fa1 --- /dev/null +++ b/test/lib/usd/ui/renderSetup/testMayaRendererProvider.cpp @@ -0,0 +1,227 @@ +// +// Copyright 2026 Autodesk +// +// 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 +// +// http://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. +// + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +namespace { + +// Exposes the protected switchRenderer() so edge cases (empty name, unknown +// name) can be exercised directly, independently of requestRenderer()'s own +// "already current" guard. +class TestableRendererProvider : public MayaUsdRenderSetup::MayaRendererProvider +{ +public: + using MayaUsdRenderSetup::MayaRendererProvider::switchRenderer; +}; + +std::string getLegacyCurrentRenderer() +{ + MString value; + MGlobal::executeCommand("getAttr defaultRenderGlobals.currentRenderer", value); + return value.asChar(); +} + +void setLegacyCurrentRenderer(const std::string& name) +{ + MString cmd; + cmd.format( + "setAttr -type \"string\" defaultRenderGlobals.currentRenderer \"^1s\"", + MString(name.c_str())); + MGlobal::executeCommand(cmd); +} + +void setHydraCurrentRenderer(const std::string& name) +{ + MayaUsd::SceneRenderDescription::setCurrentRenderer(name); +} + +using RendererInfo = AdskUsdRenderSetup::RendererInfo; + +std::vector::const_iterator +findByHydra(const std::vector& renderers, bool isHydra) +{ + return std::find_if(renderers.begin(), renderers.end(), [isHydra](const RendererInfo& r) { + return r.isHydra == isHydra; + }); +} + +// Used where the test only cares about the defaultRenderGlobals.currentRenderer +// plug's raw value, not about the name being one MayaRendererProvider actually +// knows about (i.e. not exercising the isHydra-classification branches, which +// require a name present in availableRenderers()). +const std::string kArbitraryRendererName("some-arbitrary-renderer-name"); + +} // namespace + +class MayaRendererProviderTest : public ::testing::Test +{ +protected: + void SetUp() override + { + _origLegacyRenderer = getLegacyCurrentRenderer(); + _origHydraRenderer = MayaUsd::SceneRenderDescription::getCurrentRenderer(); + } + + void TearDown() override + { + setLegacyCurrentRenderer(_origLegacyRenderer); + setHydraCurrentRenderer(_origHydraRenderer); + } + + MayaUsdRenderSetup::MayaRendererProvider provider; + +private: + std::string _origLegacyRenderer; + std::string _origHydraRenderer; +}; + +TEST_F(MayaRendererProviderTest, AvailableRenderersHasNoDuplicateNames) +{ + const auto renderers = provider.availableRenderers(); + + std::set names; + for (const auto& r : renderers) { + EXPECT_TRUE(names.insert(r.name).second) << "Duplicate renderer name: " << r.name; + } +} + +TEST_F(MayaRendererProviderTest, CurrentRendererMatchesDefaultRenderGlobalsWhenSet) +{ + setLegacyCurrentRenderer(kArbitraryRendererName); + setHydraCurrentRenderer(""); + + EXPECT_EQ(provider.currentRenderer(), kArbitraryRendererName); +} + +TEST_F(MayaRendererProviderTest, CurrentRendererFallsBackToSceneRenderDescriptionWhenLegacyEmpty) +{ + const auto renderers = provider.availableRenderers(); + const auto it = findByHydra(renderers, /*isHydra*/ true); + if (it == renderers.end()) { + GTEST_SKIP() << "No Hydra renderer plugins registered in this environment."; + } + + setLegacyCurrentRenderer(""); + setHydraCurrentRenderer(it->name); + + EXPECT_EQ(provider.currentRenderer(), it->name); +} + +TEST_F(MayaRendererProviderTest, CurrentRendererIsEmptyWhenBothStoresAreEmpty) +{ + setLegacyCurrentRenderer(""); + setHydraCurrentRenderer(""); + + EXPECT_TRUE(provider.currentRenderer().empty()); +} + +TEST_F(MayaRendererProviderTest, RequestRendererToHydraRendererUpdatesSceneRenderDescription) +{ + const auto renderers = provider.availableRenderers(); + const auto it = findByHydra(renderers, /*isHydra*/ true); + if (it == renderers.end()) { + GTEST_SKIP() << "No Hydra renderer plugins registered in this environment."; + } + + setLegacyCurrentRenderer(""); + setHydraCurrentRenderer(""); + + provider.requestRenderer(it->name); + + EXPECT_EQ(provider.currentRenderer(), it->name); + EXPECT_EQ(MayaUsd::SceneRenderDescription::getCurrentRenderer(), it->name); +} + +TEST_F(MayaRendererProviderTest, RequestRendererToLegacyRendererClearsSceneRenderDescription) +{ + const auto renderers = provider.availableRenderers(); + const auto legacyIt = findByHydra(renderers, /*isHydra*/ false); + if (legacyIt == renderers.end()) { + GTEST_SKIP() << "No legacy (non-Hydra) renderers registered in this environment."; + } + + // Seed a non-empty Hydra renderer first so we can verify the switch clears it. + const auto hydraIt = findByHydra(renderers, /*isHydra*/ true); + if (hydraIt != renderers.end()) { + setHydraCurrentRenderer(hydraIt->name); + } else { + GTEST_SKIP() << "No Hydra renderers registered in this environment."; + } + + provider.requestRenderer(legacyIt->name); + + EXPECT_EQ(provider.currentRenderer(), legacyIt->name); + EXPECT_TRUE(MayaUsd::SceneRenderDescription::getCurrentRenderer().empty()); +} + +TEST_F(MayaRendererProviderTest, RequestRendererWithUnknownNameLeavesCurrentRendererUnchanged) +{ + setLegacyCurrentRenderer(kArbitraryRendererName); + setHydraCurrentRenderer(""); + + provider.requestRenderer("totally-bogus-renderer-name-xyz"); + + EXPECT_EQ(provider.currentRenderer(), kArbitraryRendererName); +} + +TEST_F(MayaRendererProviderTest, RequestRendererAlreadyCurrentIsNoOp) +{ + setLegacyCurrentRenderer(kArbitraryRendererName); + // Sentinel: a legacy switch would clear this. If requestRenderer correctly + // treats "already current" as a no-op, switchRenderer never runs and this + // survives untouched. + setHydraCurrentRenderer("sentinel-value"); + + provider.requestRenderer(kArbitraryRendererName); + + EXPECT_EQ(provider.currentRenderer(), kArbitraryRendererName); + EXPECT_EQ(MayaUsd::SceneRenderDescription::getCurrentRenderer(), "sentinel-value"); +} + +TEST_F(MayaRendererProviderTest, SwitchRendererWithEmptyNameIsNoOp) +{ + setLegacyCurrentRenderer(kArbitraryRendererName); + setHydraCurrentRenderer("sentinel-value"); + + TestableRendererProvider testable; + testable.switchRenderer(""); + + EXPECT_EQ(getLegacyCurrentRenderer(), kArbitraryRendererName); + EXPECT_EQ(MayaUsd::SceneRenderDescription::getCurrentRenderer(), "sentinel-value"); +} + +TEST_F(MayaRendererProviderTest, SwitchRendererWithUnknownNameDoesNotTouchSceneRenderDescription) +{ + setHydraCurrentRenderer("sentinel-value"); + + TestableRendererProvider testable; + testable.switchRenderer("totally-bogus-renderer-name-xyz"); + + // An unknown name is not found in the internal renderer map, so the + // isHydra-branch that writes/clears SceneRenderDescription never runs. + EXPECT_EQ(MayaUsd::SceneRenderDescription::getCurrentRenderer(), "sentinel-value"); +}