├── .clang-format ├── .gitignore ├── .gitmodules ├── .pre-commit-config.yaml ├── CMake ├── macros │ ├── macros.cmake │ └── msvc.cmake ├── modules │ ├── FindBinaryOpenSSL.cmake │ ├── FindHoudiniUSD.cmake │ ├── FindMayaUsd.cmake │ └── FindUSDMonolithic.cmake └── templates │ ├── Config.cmake.in │ └── INSTALL.vcxproj.user.in ├── CMakeLists.txt ├── Docs └── LicenseHeader.txt ├── Examples ├── run.sh └── workspace.py ├── LICENSE ├── NOTICE ├── README.md ├── Resources ├── Icon.ico └── studio.conf ├── Sources ├── Bindings │ ├── CMakeLists.txt │ ├── __init__.py │ ├── module.cpp │ ├── moduleDeps.cpp │ ├── wrapRenderStudioKit.cpp │ └── wrapRenderStudioNotice.cpp ├── CMakeLists.txt ├── External │ └── CMakeLists.txt ├── Kit.cpp ├── Kit.h ├── Logger │ ├── CMakeLists.txt │ ├── Logger.cpp │ └── Logger.h ├── Networking │ ├── CMakeLists.txt │ ├── Certificates.cpp │ ├── Certificates.h │ ├── LocalStorageApi.cpp │ ├── LocalStorageApi.h │ ├── MaterialLibraryApi.cpp │ ├── MaterialLibraryApi.h │ ├── RestClient.cpp │ ├── RestClient.h │ ├── Url.cpp │ ├── Url.h │ ├── WebsocketClient.cpp │ ├── WebsocketClient.h │ ├── WebsocketServer.cpp │ ├── WebsocketServer.h │ ├── Workspace.cpp │ └── Workspace.h ├── Notice │ ├── CMakeLists.txt │ ├── Notice.cpp │ └── Notice.h ├── Resolver │ ├── Asset.cpp │ ├── Asset.h │ ├── CMakeLists.txt │ ├── Data.cpp │ ├── Data.h │ ├── FileFormat.cpp │ ├── FileFormat.h │ ├── Registry.cpp │ ├── Registry.h │ ├── Resolver.cpp │ ├── Resolver.h │ └── plugInfo.json ├── Schema │ ├── AiTools.cpp │ ├── AiTools.h │ ├── CMakeLists.txt │ ├── api.h │ ├── generatedSchema.usda │ ├── plugInfo.json │ ├── renderStudioAiPrimAPI.cpp │ ├── renderStudioAiPrimAPI.h │ ├── schema.usda │ ├── tokens.cpp │ ├── tokens.h │ ├── wrapRenderStudioAiPrimAPI.cpp │ └── wrapTokens.cpp ├── Serialization │ ├── Api.cpp │ ├── Api.h │ ├── CMakeLists.txt │ ├── Serialization.cpp │ └── Serialization.h ├── Server │ ├── CMakeLists.txt │ ├── Channel.cpp │ ├── Channel.h │ ├── Logic.cpp │ ├── Logic.h │ ├── Main.cpp │ ├── Run.bat │ └── Run.sh └── Utils │ ├── BackgroundTask.cpp │ ├── BackgroundTask.h │ ├── CMakeLists.txt │ ├── FileUtils.cpp │ ├── FileUtils.h │ ├── ProcessUtils.cpp │ ├── ProcessUtils.h │ ├── Uuid.cpp │ └── Uuid.h ├── Tools ├── Dockerfile.Builder ├── Dockerfile.Tester └── Makefile ├── VERSION └── Workspace ├── RenderStudioWorkspace.py ├── app ├── connection_manager.py ├── logger.py ├── main.py ├── settings.py ├── syncthing_manager.py └── terminator.py └── requirements.txt /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | 4 | BasedOnStyle: WebKit 5 | AlignAfterOpenBracket: AlwaysBreak 6 | AlwaysBreakAfterReturnType: TopLevelDefinitions 7 | AlignEscapedNewlines: Left 8 | AlignTrailingComments: 'true' 9 | AllowAllConstructorInitializersOnNextLine: 'false' 10 | AllowAllParametersOfDeclarationOnNextLine: 'false' 11 | AllowShortCaseLabelsOnASingleLine: 'false' 12 | AllowShortIfStatementsOnASingleLine: Never 13 | AllowShortLambdasOnASingleLine: All 14 | AllowShortLoopsOnASingleLine: 'false' 15 | AlwaysBreakTemplateDeclarations: MultiLine 16 | BinPackArguments: 'false' 17 | BinPackParameters: 'false' 18 | BreakBeforeBraces: Allman 19 | BreakBeforeTernaryOperators: 'true' 20 | BreakConstructorInitializers: BeforeComma 21 | BreakInheritanceList: BeforeComma 22 | ColumnLimit: '120' 23 | FixNamespaceComments: 'true' 24 | IncludeBlocks: Regroup 25 | IncludeCategories: 26 | # 1. Related header 27 | # Handled by the default IncludeIsMainRegex regex, and auto-assigned 28 | # Priority 0 29 | 30 | # 2. C++ standard library headers 31 | # angle brackets, no directory, no extension 32 | - Regex: '^<[A-Za-z0-9_-]+>$' 33 | Priority: 2 34 | 35 | # 3. C system headers 36 | # angle brackets, no directory, end with ".h" 37 | - Regex: '^<[A-Za-z0-9_-]+\.h>$' 38 | Priority: 3 39 | 40 | # 4. Pixar + USD headers 41 | - Regex: '^) 14 | endif() 15 | -------------------------------------------------------------------------------- /CMake/modules/FindUSDMonolithic.cmake: -------------------------------------------------------------------------------- 1 | # USD 20.05 does not generate cmake config for the monolithic library as it does for the default mode 2 | # So we have to handle monolithic USD in a special way 3 | 4 | if (UNIX) 5 | set (PXR_LIB_PREFIX "lib") 6 | endif () 7 | 8 | find_path(USD_INCLUDE_DIR pxr/pxr.h 9 | PATHS ${USD_LOCATION}/include 10 | $ENV{USD_LOCATION}/include 11 | DOC "USD Include directory" 12 | NO_DEFAULT_PATH 13 | NO_SYSTEM_ENVIRONMENT_PATH) 14 | 15 | find_path(USD_LIBRARY_DIR 16 | NAMES "${PXR_LIB_PREFIX}usd_usd_ms${CMAKE_SHARED_LIBRARY_SUFFIX}" 17 | PATHS ${USD_LOCATION}/lib 18 | $ENV{USD_LOCATION}/lib 19 | DOC "USD Libraries directory" 20 | NO_DEFAULT_PATH 21 | NO_SYSTEM_ENVIRONMENT_PATH) 22 | 23 | find_library(USD_MONOLITHIC_LIBRARY 24 | NAMES 25 | usd_usd_ms # Windows requires raw library name to find 26 | ${PXR_LIB_PREFIX}usd_usd_ms${CMAKE_SHARED_LIBRARY_SUFFIX} # Linux requires prefix and suffix 27 | PATHS ${USD_LIBRARY_DIR} 28 | NO_DEFAULT_PATH 29 | NO_SYSTEM_ENVIRONMENT_PATH) 30 | 31 | include(FindPackageHandleStandardArgs) 32 | 33 | find_package_handle_standard_args(USDMonolithic 34 | USD_INCLUDE_DIR 35 | USD_LIBRARY_DIR 36 | USD_MONOLITHIC_LIBRARY) 37 | 38 | if(USDMonolithic_FOUND) 39 | list(APPEND CMAKE_PREFIX_PATH ${USD_LOCATION}) 40 | 41 | # --Python. 42 | find_package(PythonInterp 3 REQUIRED) 43 | find_package(PythonLibs 3 REQUIRED) 44 | find_package(Boost REQUIRED) 45 | 46 | add_library(usd_usd_ms SHARED IMPORTED) 47 | set_property(TARGET usd_usd_ms APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) 48 | 49 | target_compile_definitions(usd_usd_ms INTERFACE 50 | -DPXR_PYTHON_ENABLED=1) 51 | target_link_libraries(usd_usd_ms INTERFACE 52 | ${USD_MONOLITHIC_LIBRARY} 53 | ${Boost_LIBRARIES} 54 | ${PYTHON_LIBRARIES}) 55 | 56 | target_link_directories(usd_usd_ms INTERFACE 57 | ${USD_LIBRARY_DIR}) 58 | target_include_directories(usd_usd_ms INTERFACE 59 | ${USD_INCLUDE_DIR} 60 | ${Boost_INCLUDE_DIRS} 61 | ${PYTHON_INCLUDE_DIRS}) 62 | set_target_properties(usd_usd_ms PROPERTIES 63 | IMPORTED_IMPLIB_RELEASE "${USD_MONOLITHIC_LIBRARY}" 64 | IMPORTED_LOCATION_RELEASE "${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}usd_usd_ms${CMAKE_SHARED_LIBRARY_SUFFIX}" 65 | ) 66 | 67 | foreach(targetName 68 | arch tf gf js trace work plug vt ar kind sdf ndr sdr pcp usd usdGeom 69 | usdVol usdLux usdMedia usdShade usdRender usdHydra usdRi usdSkel usdUI 70 | usdUtils garch hf hio cameraUtil pxOsd glf hgi hgiGL hd hdSt hdx 71 | usdImaging usdImagingGL usdRiImaging usdSkelImaging usdVolImaging 72 | usdAppUtils usdviewq) 73 | add_library(${targetName} INTERFACE) 74 | target_link_libraries(${targetName} INTERFACE usd_usd_ms) 75 | endforeach() 76 | elseif() 77 | message(FATAL "Can't find USD") 78 | endif() 79 | -------------------------------------------------------------------------------- /CMake/templates/Config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | include("${CMAKE_CURRENT_LIST_DIR}/RenderStudioTargets.cmake") 3 | check_required_components(MathFunctions) 4 | -------------------------------------------------------------------------------- /CMake/templates/INSTALL.vcxproj.user.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ${RS_VS_DEBUGGER_WORKING_DIRECTORY} 5 | ${RS_VS_DEBUGGER_ENVIRONMENT} 6 | ${RS_VS_DEBUGGER_COMMAND} 7 | ${RS_VS_DEBUGGER_COMMAND_ARGUMENTS} 8 | 9 | 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | project(RenderStudioKit VERSION 0.3 LANGUAGES CXX) 17 | 18 | # Options 19 | option(WITH_SHARED_WORKSPACE_SUPPORT "Enables shared workspace feature. Requires pyinstaller to be installed" ON) 20 | option(WITH_PYTHON_DEPENDENCIES_INSTALL "Enables automatic install for all build requirements for Python" ON) 21 | 22 | # Config 23 | set(CMAKE_CXX_STANDARD 17) 24 | set(CMAKE_CXX_STANDARD_REQUIRED True) 25 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 26 | 27 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/modules) 28 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/defaults) 29 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/macros) 30 | 31 | include(${CMAKE_SOURCE_DIR}/CMake/macros/macros.cmake) 32 | include(${CMAKE_SOURCE_DIR}/CMake/macros/msvc.cmake) 33 | 34 | add_subdirectory(Sources) 35 | 36 | # Install license 37 | install(FILES ${CMAKE_SOURCE_DIR}/LICENSE ${CMAKE_SOURCE_DIR}/NOTICE DESTINATION share/doc/${CMAKE_PROJECT_NAME}) 38 | 39 | # Install RenderStudioTargets.cmake 40 | include(CMakePackageConfigHelpers) 41 | set(KIT_TARGETS RenderStudioKit RenderStudioResolver RenderStudioNetworking RenderStudioLogger RenderStudioUtils RenderStudioNotice) 42 | set(KIT_DEPENDENCIES fmt uriparser zip) 43 | 44 | if(NOT HOUDINI_SUPPORT) 45 | list(APPEND KIT_TARGETS RenderStudioSchema) 46 | endif() 47 | 48 | install(TARGETS ${KIT_TARGETS} ${KIT_DEPENDENCIES} 49 | EXPORT RenderStudioTargets 50 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 51 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 52 | # RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} Commented out since we have duplication of dll's for now 53 | # INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} Commented out since each target installs own includes 54 | ) 55 | 56 | install(EXPORT RenderStudioTargets 57 | FILE RenderStudioTargets.cmake 58 | NAMESPACE RenderStudio:: 59 | DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake 60 | ) 61 | 62 | # Install RenderStudioConfig.cmake 63 | configure_package_config_file( 64 | ${PROJECT_SOURCE_DIR}/CMake/templates/Config.cmake.in 65 | "${CMAKE_CURRENT_BINARY_DIR}/RenderStudioConfig.cmake" 66 | INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake/ 67 | ) 68 | 69 | install(FILES 70 | "${CMAKE_CURRENT_BINARY_DIR}/RenderStudioConfig.cmake" 71 | DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake/ 72 | ) 73 | 74 | # Build workspace 75 | if (WITH_SHARED_WORKSPACE_SUPPORT) 76 | # Install build dependencies with pip 77 | if (WITH_PYTHON_DEPENDENCIES_INSTALL) 78 | find_program(PIP_EXECUTABLE REQUIRED NAMES pip3 pip) 79 | set(REQUIREMENTS_FILE ${CMAKE_SOURCE_DIR}/Workspace/requirements.txt) 80 | set(INSTALLED_REQUIREMENTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/installed_requirements.txt) 81 | 82 | # Custom command to check if requirements have changed 83 | add_custom_command( 84 | OUTPUT ${INSTALLED_REQUIREMENTS_FILE} 85 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 86 | ${REQUIREMENTS_FILE} ${INSTALLED_REQUIREMENTS_FILE} 87 | COMMAND ${PIP_EXECUTABLE} install -r ${REQUIREMENTS_FILE} 88 | DEPENDS ${REQUIREMENTS_FILE} 89 | COMMENT "Checking and installing python dependencies if required" 90 | ) 91 | 92 | # Custom target for installing Python dependencies 93 | add_custom_target( 94 | InstallPythonDeps ALL 95 | DEPENDS ${INSTALLED_REQUIREMENTS_FILE} 96 | ) 97 | else() 98 | find_program(NUITKA_EXECUTABLE REQUIRED NAMES nuitka.bat) 99 | endif() 100 | 101 | if (WIN32) 102 | set(WORKSPACE_EXE_NAME "RenderStudioWorkspace.exe") 103 | endif() 104 | 105 | if (UNIX) 106 | set(WORKSPACE_EXE_NAME "RenderStudioWorkspace.bin") 107 | endif() 108 | 109 | file(GLOB_RECURSE PYTHON_SOURCE_FILES ${CMAKE_SOURCE_DIR}/Workspace/*.py) 110 | 111 | # Define the output of the command, i.e., the path of the executable produced by Nuitka 112 | set(NUITKA_OUTPUT_EXE ${CMAKE_CURRENT_BINARY_DIR}/nuitka/RenderStudioWorkspace.dist/${WORKSPACE_EXE_NAME}) 113 | if (NOT PYTHON_EXECUTABLE) 114 | find_program(PYTHON_EXECUTABLE REQUIRED NAMES python3 python) 115 | endif() 116 | 117 | # Define a custom command that compiles the Python script into an executable 118 | # This command will only run if the output file (Nuitka executable) is missing or if any of the PYTHON_SOURCE_FILES have changed. 119 | add_custom_command( 120 | OUTPUT ${NUITKA_OUTPUT_EXE} 121 | COMMAND ${PYTHON_EXECUTABLE} -m nuitka 122 | --output-dir=${CMAKE_CURRENT_BINARY_DIR}/nuitka 123 | --standalone 124 | --assume-yes-for-downloads 125 | --windows-icon-from-ico=${CMAKE_SOURCE_DIR}/Resources/Icon.ico 126 | --msvc=14.2 127 | ${CMAKE_SOURCE_DIR}/Workspace/RenderStudioWorkspace.py 128 | DEPENDS ${PYTHON_SOURCE_FILES} 129 | COMMENT "Building executable of RenderStudioWorkspace using nuitka" 130 | ) 131 | 132 | # Define a custom target that depends on the Nuitka output executable 133 | # This target will run every time, but the custom command above will only re-execute if its dependencies are updated. 134 | add_custom_target( 135 | ExecuteNuitka ALL 136 | DEPENDS ${NUITKA_OUTPUT_EXE} 137 | ) 138 | 139 | # Optionally, ensure that Python dependencies are installed before Nuitka is executed. 140 | if (WITH_PYTHON_DEPENDENCIES_INSTALL) 141 | add_dependencies(ExecuteNuitka InstallPythonDeps) 142 | endif() 143 | 144 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/nuitka/RenderStudioWorkspace.dist/ 145 | DESTINATION ${CMAKE_INSTALL_PREFIX}/plugin/usd/RenderStudioWorkspace 146 | USE_SOURCE_PERMISSIONS 147 | ) 148 | endif() 149 | -------------------------------------------------------------------------------- /Docs/LicenseHeader.txt: -------------------------------------------------------------------------------- 1 | Copyright 2023 Advanced Micro Devices, Inc 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Examples/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"/mnt/Build/Install/USD/lib" 4 | export PYTHONPATH="/mnt/Build/Install/USD/lib/python" 5 | 6 | python3 /mnt/Kit/Examples/workspace.py 7 | -------------------------------------------------------------------------------- /Examples/workspace.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import time 16 | from rs import RenderStudioKit as kit 17 | import rs 18 | 19 | kit.SetWorkspacePath("/mnt/WorkspaceTest") 20 | # kit.SetWorkspaceUrl("http://...") 21 | kit.SharedWorkspaceConnect(kit.Role.Client) 22 | 23 | time.sleep(90) 24 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | AMD RenderStudioKit 2 | Copyright 2023 Advanced Micro Devices, Inc 3 | 4 | ================================================================================ 5 | https://github.com/PixarAnimationStudios/OpenUSD 6 | -------------------------------------------------------------------------------- 7 | Universal Scene Description 8 | Copyright 2016 Pixar 9 | 10 | All rights reserved. 11 | 12 | 13 | 14 | This product includes software developed at: 15 | 16 | Pixar (http://www.pixar.com/). 17 | ================================================================================ 18 | https://github.com/boostorg/boost 19 | -------------------------------------------------------------------------------- 20 | Boost Software License - Version 1.0 - August 17th, 2003 21 | 22 | Permission is hereby granted, free of charge, to any person or organization 23 | obtaining a copy of the software and accompanying documentation covered by 24 | this license (the "Software") to use, reproduce, display, distribute, 25 | execute, and transmit the Software, and to prepare derivative works of the 26 | Software, and to permit third-parties to whom the Software is furnished to 27 | do so, all subject to the following: 28 | 29 | The copyright notices in the Software and this entire statement, including 30 | the above license grant, this restriction and the following disclaimer, 31 | must be included in all copies of the Software, in whole or in part, and 32 | all derivative works of the Software, unless such copies or derivative 33 | works are solely in the form of machine-executable object code generated by 34 | a source language processor. 35 | 36 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 39 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 40 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 41 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 42 | DEALINGS IN THE SOFTWARE. 43 | ================================================================================ 44 | https://github.com/syncthing/syncthing 45 | -------------------------------------------------------------------------------- 46 | This software uses Syncthing tool which is licensed under 47 | Mozilla Public License Version 2.0 48 | ================================================================================ 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AMD RenderStudio Kit 2 | This repo contains all required methods to integrate USD software into AMD RenderStudio ecosystem 3 | 4 | ## Quick start 5 | ### Build OpenUSD 6 | ```bash 7 | cd OpenUSD 8 | python build_scripts\build_usd.py --openimageio --materialx --src Downloads --build Build Install --build-args "boost, --with-log" 9 | ``` 10 | 11 | ### Build RenderStudioKit 12 | ```bash 13 | cd RenderStudioKit 14 | cmake -B Build -DCMAKE_PREFIX_PATH= -DCMAKE_INSTALL_PREFIX= 15 | cmake --build Build --config Release 16 | ``` 17 | 18 | ## Build overview 19 | ### Dependencies 20 | ```bash 21 | pip3 install -r Workspace/requirements.txt 22 | ``` 23 | > Please note CMake would install pip requirements during build by default. Consider use WITH_PYTHON_DEPENDENCIES_INSTALL option to disable this. 24 | ### CMake options 25 | ```bash 26 | WITH_SHARED_WORKSPACE_SUPPORT [ON] - Enables shared workspace feature. Requires pyinstaller to be installed 27 | WITH_PYTHON_DEPENDENCIES_INSTALL [ON] - Enables automatic install for all build requirements for Python 28 | USD_LOCATION [""] - Here CMAKE_INSTALL_PREFIX of USD build should be passed 29 | ``` 30 | 31 | ## Deployment 32 | ### Prepare directories on remote 33 | ```bash 34 | sudo mkdir -p /opt/rs/ && sudo chown $(whoami) /opt/rs 35 | sudo mkdir -p "/var/lib/AMD/AMD RenderStudio/" && sudo chown $(whoami) "/var/lib/AMD/AMD RenderStudio/" 36 | ``` 37 | ### Deploy from builder 38 | - Set **studio** remote in ~/.ssh/config 39 | ```bash 40 | make -C Kit/Tools/ deploy 41 | ``` 42 | ### Nginx config sample 43 | ```bash 44 | server { 45 | # Redirect workspace requests to RenderStudioWorkspace 46 | location /workspace/ { 47 | proxy_pass http://127.0.0.1:52700; 48 | } 49 | 50 | # Redirect live requests to RenderStudioServer 51 | location /workspace/live/ { 52 | proxy_pass http://127.0.0.1:52702/; 53 | proxy_http_version 1.1; 54 | proxy_set_header Upgrade $http_upgrade; 55 | proxy_set_header Connection "upgrade"; 56 | } 57 | } 58 | ``` 59 | 60 | ## Running 61 | ### Launch server 62 | ```bash 63 | /opt/rs/RenderStudioServer/Run.sh 64 | ``` 65 | -------------------------------------------------------------------------------- /Resources/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/RenderStudioKit/f5ca2da7931e18175e9add1561d64c2885d487e1/Resources/Icon.ico -------------------------------------------------------------------------------- /Resources/studio.conf: -------------------------------------------------------------------------------- 1 | server { 2 | # Redirect workspace requests to RenderStudioWorkspace 3 | location /workspace/ { 4 | proxy_pass http://127.0.0.1:52700; 5 | } 6 | 7 | # Redirect live requests to RenderStudioServer 8 | location /workspace/live/ { 9 | proxy_pass http://127.0.0.1:52702/; 10 | proxy_http_version 1.1; 11 | proxy_set_header Upgrade $http_upgrade; 12 | proxy_set_header Connection "upgrade"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Sources/Bindings/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | 17 | set(USDPLUGIN_NAME ${CMAKE_PROJECT_NAME}) 18 | set(USDPLUGIN_PYTHON_NAME _${USDPLUGIN_NAME}) 19 | 20 | add_library(${USDPLUGIN_PYTHON_NAME} SHARED 21 | module.cpp 22 | moduleDeps.cpp 23 | wrapRenderStudioKit.cpp 24 | wrapRenderStudioNotice.cpp 25 | ) 26 | 27 | target_link_libraries(${USDPLUGIN_PYTHON_NAME} PRIVATE 28 | Boost::boost 29 | Boost::python 30 | Boost::log 31 | RenderStudioKit 32 | RenderStudioResolver 33 | RenderStudioNetworking 34 | RenderStudioUtils 35 | RenderStudioNotice 36 | usd 37 | ) 38 | if (TBB_INCLUDE_DIR) 39 | target_include_directories(${USDPLUGIN_PYTHON_NAME} PRIVATE ${TBB_INCLUDE_DIR}) 40 | target_link_libraries(${USDPLUGIN_PYTHON_NAME} PRIVATE ${TBB_LIBRARY}) 41 | endif() 42 | 43 | target_include_directories(${USDPLUGIN_PYTHON_NAME} PRIVATE ..) 44 | 45 | target_compile_definitions(${USDPLUGIN_PYTHON_NAME} 46 | PRIVATE 47 | MFB_PACKAGE_NAME=${USDPLUGIN_NAME} 48 | MFB_ALT_PACKAGE_NAME=${USDPLUGIN_NAME} 49 | MFB_PACKAGE_MODULE=rs.${USDPLUGIN_NAME} 50 | NOMINMAX 51 | ) 52 | 53 | set_property(TARGET ${USDPLUGIN_PYTHON_NAME} PROPERTY PREFIX "") 54 | 55 | if (WIN32) 56 | set_property(TARGET ${USDPLUGIN_PYTHON_NAME} PROPERTY SUFFIX ".pyd") 57 | endif() 58 | 59 | # Install python wrapper 60 | install(TARGETS ${USDPLUGIN_PYTHON_NAME} DESTINATION lib/python/rs/${USDPLUGIN_NAME}) 61 | install(FILES __init__.py DESTINATION lib/python/rs/${USDPLUGIN_NAME}) 62 | -------------------------------------------------------------------------------- /Sources/Bindings/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from . import _RenderStudioKit 16 | from pxr import Tf 17 | Tf.PrepareModule(_RenderStudioKit, locals()) 18 | del Tf 19 | 20 | try: 21 | import __DOC 22 | __DOC.Execute(locals()) 23 | del __DOC 24 | except Exception: 25 | try: 26 | import __tmpDoc 27 | __tmpDoc.Execute(locals()) 28 | del __tmpDoc 29 | except: 30 | pass 31 | -------------------------------------------------------------------------------- /Sources/Bindings/module.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | PXR_NAMESPACE_USING_DIRECTIVE 19 | 20 | TF_WRAP_MODULE 21 | { 22 | TF_WRAP(RenderStudioKit); 23 | TF_WRAP(RenderStudioNotice); 24 | } 25 | -------------------------------------------------------------------------------- /Sources/Bindings/moduleDeps.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | PXR_NAMESPACE_OPEN_SCOPE 23 | 24 | TF_REGISTRY_FUNCTION(TfScriptModuleLoader) 25 | { 26 | // List of direct dependencies for this library. 27 | const std::vector reqs = { TfToken("ar"), TfToken("sdf") }; 28 | 29 | TfScriptModuleLoader::GetInstance().RegisterLibrary( 30 | TfToken("RenderStudioKit"), TfToken("rs.RenderStudioKit"), reqs); 31 | } 32 | 33 | PXR_NAMESPACE_CLOSE_SCOPE 34 | -------------------------------------------------------------------------------- /Sources/Bindings/wrapRenderStudioKit.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "../Kit.h" 16 | 17 | #ifdef HOUDINI_SUPPORT 18 | #include 19 | #include 20 | #include 21 | using namespace hboost::python; 22 | #else 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | using namespace boost::python; 31 | #endif 32 | 33 | void 34 | wrapRenderStudioKit() 35 | { 36 | using namespace RenderStudio::Kit; 37 | 38 | enum_("Role") 39 | .value("Server", Role::Server) 40 | .value("Client", Role::Client) 41 | ; 42 | 43 | def("LiveSessionConnect", &LiveSessionConnect, args("info")); 44 | def("LiveSessionUpdate", &LiveSessionUpdate); 45 | def("LiveSessionDisconnect", &LiveSessionDisconnect); 46 | 47 | def("SharedWorkspaceConnect", &SharedWorkspaceConnect, args("role")); 48 | def("SharedWorkspaceDisconnect", &SharedWorkspaceDisconnect); 49 | 50 | def("IsUnresolvable", &IsUnresolvable, args("path")); 51 | def("Unresolve", &Unresolve, args("path")); 52 | def("IsRenderStudioPath", &IsRenderStudioPath, args("path")); 53 | def("SetWorkspacePath", &SetWorkspacePath, args("path")); 54 | def("GetWorkspacePath", &GetWorkspacePath); 55 | def("GetDefaultWorkspacePath", &GetDefaultWorkspacePath); 56 | def("SetWorkspaceUrl", &SetWorkspaceUrl, args("url")); 57 | def("GetWorkspaceUrl", &GetWorkspaceUrl); 58 | 59 | class_("LiveSessionInfo" /*, init()*/) 60 | .add_property("liveUrl", &LiveSessionInfo::liveUrl) 61 | .add_property("storageUrl", &LiveSessionInfo::storageUrl) 62 | .add_property("channelId", &LiveSessionInfo::channelId) 63 | .add_property("userId", &LiveSessionInfo::userId); 64 | }; 65 | -------------------------------------------------------------------------------- /Sources/Bindings/wrapRenderStudioNotice.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #ifdef HOUDINI_SUPPORT 23 | #include 24 | #include 25 | #include 26 | using namespace hboost::python; 27 | #else 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | using namespace boost::python; 36 | #endif 37 | 38 | PXR_NAMESPACE_USING_DIRECTIVE 39 | 40 | namespace 41 | { 42 | 43 | TF_INSTANTIATE_NOTICE_WRAPPER(RenderStudioNotice::WorkspaceState, TfNotice) 44 | TF_INSTANTIATE_NOTICE_WRAPPER(RenderStudioNotice::FileUpdated, TfNotice) 45 | TF_INSTANTIATE_NOTICE_WRAPPER(RenderStudioNotice::WorkspaceConnectionChanged, TfNotice) 46 | 47 | } // anonymous namespace 48 | 49 | void wrapRenderStudioNotice() { 50 | scope s = class_("Notice", no_init); 51 | 52 | TfPyNoticeWrapper< 53 | RenderStudioNotice::WorkspaceConnectionChanged, TfNotice>::Wrap() 54 | .def("IsConnected", &RenderStudioNotice::WorkspaceConnectionChanged::IsConnected) 55 | ; 56 | 57 | TfPyNoticeWrapper< 58 | RenderStudioNotice::FileUpdated, TfNotice>::Wrap() 59 | .def("GetPath", &RenderStudioNotice::FileUpdated::GetPath) 60 | ; 61 | 62 | TfPyNoticeWrapper< 63 | RenderStudioNotice::WorkspaceState, TfNotice>::Wrap() 64 | .def("GetState", &RenderStudioNotice::WorkspaceState::GetState) 65 | ; 66 | 67 | enum_("RenderStudioNotice::WorkspaceState::State") 68 | .value("Idle", RenderStudioNotice::WorkspaceState::State::Idle) 69 | .value("Syncing", RenderStudioNotice::WorkspaceState::State::Syncing) 70 | .value("Error", RenderStudioNotice::WorkspaceState::State::Error) 71 | .value("Other", RenderStudioNotice::WorkspaceState::State::Other) 72 | ; 73 | }; 74 | -------------------------------------------------------------------------------- /Sources/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | 17 | find_package(OpenSSL REQUIRED) 18 | 19 | # Create target 20 | file(GLOB SOURCES *.h *.cpp) 21 | add_library(${PROJECT_NAME} STATIC ${SOURCES}) 22 | 23 | 24 | # Find packages 25 | if(MAYA_SUPPORT) 26 | find_package(MayaUsd REQUIRED) 27 | 28 | # perform find package after we listed all necessary directoris in Find mayausd package 29 | find_package(Boost REQUIRED COMPONENTS python log) 30 | else() 31 | find_package(Boost REQUIRED COMPONENTS python log) 32 | if(HOUDINI_SUPPORT) 33 | find_package(HoudiniUSD REQUIRED) 34 | else() 35 | if (PXR_BUILD_MONOLITHIC) 36 | find_package(USDMonolithic REQUIRED) 37 | else() 38 | find_package(pxr REQUIRED CONFIG) 39 | endif() 40 | endif() 41 | endif() 42 | 43 | # Add dependencies 44 | add_subdirectory(External) 45 | add_subdirectory(Logger) 46 | add_subdirectory(Networking) 47 | add_subdirectory(Serialization) 48 | add_subdirectory(Server) 49 | add_subdirectory(Resolver) 50 | add_subdirectory(Utils) 51 | add_subdirectory(Notice) 52 | 53 | if(NOT HOUDINI_SUPPORT) 54 | add_subdirectory(Schema) 55 | target_link_libraries(${PROJECT_NAME} PRIVATE RenderStudioSchema) 56 | endif() 57 | 58 | if (PXR_ENABLE_PYTHON_SUPPORT) 59 | add_subdirectory(Bindings) 60 | endif() 61 | 62 | # Link libraries 63 | target_link_libraries(${PROJECT_NAME} PRIVATE 64 | $ 65 | $ 66 | $ 67 | $ 68 | RenderStudioResolver 69 | RenderStudioNetworking 70 | RenderStudioLogger 71 | ) 72 | 73 | if (TBB_INCLUDE_DIR) 74 | target_include_directories(${PROJECT_NAME} PRIVATE ${TBB_INCLUDE_DIR}) 75 | endif() 76 | 77 | # Set compile options 78 | SetDefaultCompileDefinitions(${PROJECT_NAME}) 79 | SetMaxWarningLevel(${PROJECT_NAME}) 80 | SetVisualStudioDebuggerOptions(${PROJECT_NAME}) 81 | 82 | install(FILES Kit.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/RenderStudio) 83 | 84 | # Export target 85 | set_target_properties(${PROJECT_NAME} 86 | PROPERTIES EXPORT_NAME Kit 87 | ) 88 | 89 | target_include_directories(${PROJECT_NAME} 90 | PUBLIC 91 | "$" 92 | "$/include>" 93 | ) 94 | 95 | # Downlaod syncthing 96 | include(FetchContent) 97 | 98 | if (WIN32) 99 | FetchContent_Declare( 100 | syncthing 101 | URL https://github.com/syncthing/syncthing/releases/download/v1.25.0/syncthing-windows-amd64-v1.25.0.zip 102 | URL_HASH SHA256=fbd89a9e2893f778b8379f151b50c922c72ac73e8af03317480f3a2ad9eb7aeb 103 | ) 104 | endif() 105 | 106 | if (UNIX) 107 | FetchContent_Declare( 108 | syncthing 109 | URL https://github.com/syncthing/syncthing/releases/download/v1.25.0/syncthing-linux-amd64-v1.25.0.tar.gz 110 | URL_HASH SHA256=c16d62bc54659c27728b3501786240a06e29dd553204fd01b2968cad0bb03e4e 111 | ) 112 | endif() 113 | 114 | FetchContent_GetProperties(syncthing) 115 | 116 | if(NOT syncthing_POPULATED) 117 | FetchContent_Populate(syncthing) 118 | endif() 119 | 120 | if (WIN32) 121 | install(FILES ${syncthing_SOURCE_DIR}/syncthing.exe 122 | DESTINATION ${CMAKE_INSTALL_PREFIX}/plugin/usd/RenderStudioWorkspace) 123 | endif() 124 | 125 | if (UNIX) 126 | install(FILES ${syncthing_SOURCE_DIR}/syncthing 127 | DESTINATION ${CMAKE_INSTALL_PREFIX}/plugin/usd/RenderStudioWorkspace 128 | PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) 129 | endif() 130 | -------------------------------------------------------------------------------- /Sources/External/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Set policies 16 | set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) 17 | 18 | # Add targets 19 | set(URIPARSER_BUILD_TESTS OFF) 20 | set(URIPARSER_BUILD_TOOLS OFF) 21 | set(URIPARSER_BUILD_DOCS OFF) 22 | set(BUILD_SHARED_LIBS OFF) 23 | 24 | set(_saved_CMAKE_MESSAGE_LOG_LEVEL ${CMAKE_MESSAGE_LOG_LEVEL}) 25 | set(CMAKE_MESSAGE_LOG_LEVEL NOTICE) 26 | add_subdirectory(fmt) 27 | add_subdirectory(uriparser) 28 | add_subdirectory(zip) 29 | set(CMAKE_MESSAGE_LOG_LEVEL ${_saved_CMAKE_MESSAGE_LOG_LEVEL}) 30 | 31 | # Create static library 32 | set_target_properties(fmt uriparser zip uninstall PROPERTIES FOLDER HiddenTargets) 33 | 34 | if (NOT MSVC) 35 | set_property(TARGET ${PROJECT_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) 36 | set_property(TARGET fmt PROPERTY POSITION_INDEPENDENT_CODE ON) 37 | set_property(TARGET uriparser PROPERTY POSITION_INDEPENDENT_CODE ON) 38 | set_property(TARGET zip PROPERTY POSITION_INDEPENDENT_CODE ON) 39 | endif() 40 | -------------------------------------------------------------------------------- /Sources/Kit.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Kit.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace RenderStudio::Kit 23 | { 24 | 25 | void 26 | LiveSessionConnect(const LiveSessionInfo& info) 27 | { 28 | pxr::RenderStudioResolver::StartLiveMode(info); 29 | } 30 | 31 | bool 32 | LiveSessionUpdate() 33 | { 34 | return pxr::RenderStudioResolver::ProcessLiveUpdates(); 35 | } 36 | 37 | void 38 | LiveSessionDisconnect() 39 | { 40 | pxr::RenderStudioResolver::StopLiveMode(); 41 | } 42 | 43 | void 44 | SharedWorkspaceConnect(Role role) 45 | { 46 | RenderStudio::Networking::Workspace::Connect(role); 47 | } 48 | 49 | void 50 | SharedWorkspaceDisconnect() 51 | { 52 | RenderStudio::Networking::Workspace::Disconnect(); 53 | } 54 | 55 | bool 56 | SharedWorkspaceIsConnected() 57 | { 58 | return RenderStudio::Networking::Workspace::IsConnected(); 59 | } 60 | 61 | bool 62 | SharedWorkspaceIsIdle() 63 | { 64 | return RenderStudio::Networking::Workspace::IsIdle(); 65 | } 66 | 67 | void 68 | SharedWorkspaceWaitIdle() 69 | { 70 | RenderStudio::Networking::Workspace::WaitIdle(); 71 | } 72 | 73 | void 74 | SharedWorkspacePause() 75 | { 76 | RenderStudio::Networking::Workspace::Pause(); 77 | } 78 | 79 | void 80 | SharedWorkspaceResume() 81 | { 82 | RenderStudio::Networking::Workspace::Resume(); 83 | } 84 | 85 | bool 86 | IsUnresolvable(const std::string& path) 87 | { 88 | return pxr::RenderStudioResolver::IsUnresolvable(path); 89 | } 90 | 91 | std::string 92 | Unresolve(const std::string& path) 93 | { 94 | return pxr::RenderStudioResolver::Unresolve(path); 95 | } 96 | 97 | bool 98 | IsRenderStudioPath(const std::string& path) 99 | { 100 | return pxr::RenderStudioResolver::IsRenderStudioPath(path); 101 | } 102 | 103 | void 104 | SetWorkspacePath(const std::string& path) 105 | { 106 | pxr::RenderStudioResolver::SetWorkspacePath(path); 107 | RenderStudio::Networking::Workspace::SetWorkspacePath(path); 108 | LOG_INFO << "Set workspace path to: " << path; 109 | } 110 | 111 | void 112 | SetWorkspaceUrl(const std::string& url) 113 | { 114 | RenderStudio::Networking::Workspace::SetWorkspaceUrl(url); 115 | LOG_INFO << "Set URL of remote workspace server to: " << url; 116 | } 117 | 118 | std::string 119 | GetWorkspacePath() 120 | { 121 | return pxr::RenderStudioResolver::GetWorkspacePath(); 122 | } 123 | 124 | std::string 125 | GetDefaultWorkspacePath() 126 | { 127 | return RenderStudio::Utils::GetDefaultWorkspacePath().string(); 128 | } 129 | 130 | std::string 131 | GetWorkspaceUrl() 132 | { 133 | return RenderStudio::Networking::Workspace::GetWorkspaceUrl(); 134 | } 135 | 136 | } // namespace RenderStudio::Kit 137 | -------------------------------------------------------------------------------- /Sources/Kit.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | #include 17 | 18 | namespace RenderStudio::Kit 19 | { 20 | 21 | // ========== Live Sessions API ========== 22 | 23 | struct LiveSessionInfo 24 | { 25 | std::string liveUrl; 26 | std::string storageUrl; 27 | std::string channelId; 28 | std::string userId; 29 | }; 30 | 31 | /// @brief Connects to remote live server. 32 | /// @param info Structure containing neccessary URL's and ID's to establish live connection. 33 | void LiveSessionConnect(const LiveSessionInfo& info); 34 | 35 | /// @brief Must be called from USD thread. Pushes local updates and pulls remote updates. 36 | bool LiveSessionUpdate(); 37 | 38 | /// @brief Disconnects from remote live server. 39 | void LiveSessionDisconnect(); 40 | 41 | // ========== File Syncing API ========== 42 | 43 | enum class Role 44 | { 45 | Server, 46 | Client 47 | }; 48 | 49 | /// @brief Starts file sharing for inside workspace directory. 50 | void SharedWorkspaceConnect(Role role = Role::Client); 51 | 52 | /// @brief Stops file sharing for inside workspace directory. 53 | void SharedWorkspaceDisconnect(); 54 | 55 | /// @brief Checks if connected to shared workspace 56 | bool SharedWorkspaceIsConnected(); 57 | 58 | /// @brief Checks if synchronization is finished. 59 | bool SharedWorkspaceIsIdle(); 60 | 61 | /// @brief Waits for synchronization to be finished. 62 | void SharedWorkspaceWaitIdle(); 63 | 64 | /// @brief Pauses synchronization. Useful to be sure files aren't locked by syncthing 65 | void SharedWorkspacePause(); 66 | 67 | /// @brief Resumes synchronization. 68 | void SharedWorkspaceResume(); 69 | 70 | /// @brief Set directory which would be synchronized for all connected users 71 | /// @param path Directory to syncronize 72 | void SetWorkspacePath(const std::string& path); 73 | 74 | /// @brief Set remote URL for remote workspace server 75 | /// @param url URL of remote workspace server 76 | void SetWorkspaceUrl(const std::string& url); 77 | 78 | /// @brief Get current directory which would be synchronized for all connected users 79 | std::string GetWorkspacePath(); 80 | 81 | /// @brief Get default directory which would be synchronized for all connected users 82 | std::string GetDefaultWorkspacePath(); 83 | 84 | /// @brief Get current remote URL for remote workspace server 85 | std::string GetWorkspaceUrl(); 86 | 87 | // ========== SdfPath Utils API ========== 88 | 89 | /// @brief Checks if provided path could be transformed into RenderStudio path 90 | /// @param path Path to check 91 | /// @return True if path convertible to RenderStudio path 92 | bool IsUnresolvable(const std::string& path); 93 | 94 | /// @brief Convert local filesystem path from local path into RenderStudio path 95 | /// @param path Local filesystem path 96 | /// @return RenderStudio filesystem path 97 | std::string Unresolve(const std::string& path); 98 | 99 | /// @brief Checks if provided path is render studio path 100 | /// @param path Path to check 101 | /// @return True if path is RenderStudio path 102 | bool IsRenderStudioPath(const std::string& path); 103 | 104 | } // namespace RenderStudio::Kit 105 | -------------------------------------------------------------------------------- /Sources/Logger/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | set(KIT_TARGET_NAME "RenderStudioLogger") 17 | 18 | set(CMAKE_CXX_STANDARD 20) 19 | 20 | # Create target 21 | file(GLOB SOURCES *.h *.cpp) 22 | add_library(${KIT_TARGET_NAME} STATIC ${SOURCES}) 23 | 24 | # Link libraries 25 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 26 | Boost::boost 27 | Boost::log 28 | fmt::fmt 29 | ) 30 | 31 | target_link_libraries(${KIT_TARGET_NAME} INTERFACE 32 | Boost::log 33 | ) 34 | 35 | SetDefaultCompileDefinitions(${KIT_TARGET_NAME}) 36 | SetMaxWarningLevel(${KIT_TARGET_NAME}) 37 | -------------------------------------------------------------------------------- /Sources/Logger/Logger.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Logger.h" 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #pragma warning(pop) 33 | 34 | namespace logging = boost::log; 35 | namespace expr = boost::log::expressions; 36 | namespace sinks = boost::log::sinks; 37 | 38 | namespace RenderStudio 39 | { 40 | 41 | void 42 | coloring_formatter(logging::record_view const& rec, logging::wformatting_ostream& strm) 43 | { 44 | // Time section 45 | strm << fmt::format( 46 | fg(fmt::color::dim_gray), expr::format_date_time("TimeStamp", "%H:%M")(rec)) 47 | << " "; 48 | 49 | // Serverity section 50 | auto severity = rec[logging::trivial::severity]; 51 | 52 | if (severity) 53 | { 54 | // Set the color 55 | switch (severity.get()) 56 | { 57 | case logging::trivial::severity_level::trace: 58 | strm << fmt::format(fg(fmt::color::light_steel_blue), "[studio]"); 59 | strm << " 🕵️‍♂️ "; 60 | break; 61 | case logging::trivial::severity_level::debug: 62 | strm << fmt::format(fg(fmt::color::cornflower_blue), "[studio]"); 63 | strm << " 🔍 "; 64 | break; 65 | case logging::trivial::severity_level::info: 66 | strm << fmt::format(fg(fmt::color::light_green), "[studio]"); 67 | strm << " ✅ "; 68 | break; 69 | case logging::trivial::severity_level::warning: 70 | strm << fmt::format(fg(fmt::color::yellow), "[studio]"); 71 | strm << fmt::format(fg(fmt::color::yellow) | fmt::emphasis::bold, " ⚠️ "); 72 | break; 73 | case logging::trivial::severity_level::error: 74 | strm << fmt::format(fg(fmt::color::orange_red), "[studio]"); 75 | strm << " ❌ "; 76 | break; 77 | case logging::trivial::severity_level::fatal: 78 | strm << fmt::format(fg(fmt::color::red), "[studio]"); 79 | strm << " ⛔ "; 80 | break; 81 | default: 82 | break; 83 | } 84 | } 85 | 86 | // Message section 87 | strm << rec[expr::smessage] << " "; 88 | 89 | // Function and line section 90 | std::string function = "(" + logging::extract("Function", rec).get() + ":" 91 | + std::to_string(logging::extract("Line", rec).get()) + ")"; 92 | strm << fmt::format(fg(fmt::color::dim_gray), function); 93 | } 94 | 95 | BOOST_LOG_GLOBAL_LOGGER_INIT(logger, RenderStudioLogger) 96 | { 97 | logging::add_common_attributes(); 98 | 99 | // Shared pointer for the backend 100 | auto backend = boost::make_shared(); 101 | backend->add_stream(boost::shared_ptr(&std::wcout, boost::null_deleter())); 102 | backend->auto_flush(true); 103 | 104 | // Create the sink 105 | using sink_t = sinks::asynchronous_sink; 106 | auto sink = boost::make_shared(backend); 107 | sink->set_formatter(&coloring_formatter); 108 | boost::log::core::get()->add_sink(sink); 109 | 110 | RenderStudioLogger logger; 111 | return logger; 112 | } 113 | 114 | } // namespace RenderStudio 115 | -------------------------------------------------------------------------------- /Sources/Logger/Logger.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #define _FUNCTION_NAME __FUNCTION__ 18 | 19 | #pragma warning(push, 0) 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #pragma warning(pop) 26 | 27 | namespace RenderStudio 28 | { 29 | 30 | using RenderStudioLogger = boost::log::sources::severity_logger_mt; 31 | BOOST_LOG_GLOBAL_LOGGER(logger, RenderStudioLogger) 32 | 33 | } // namespace RenderStudio 34 | 35 | #define _LOG_SET(_severity) \ 36 | boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::_severity) 37 | #define LOG_SET_TRACE() _LOG_SET(trace) 38 | #define LOG_SET_DEBUG() _LOG_SET(debug) 39 | #define LOG_SET_INFO() _LOG_SET(info) 40 | #define LOG_SET_WARNING() _LOG_SET(warning) 41 | #define LOG_SET_ERROR() _LOG_SET(error) 42 | #define LOG_SET_FATAL() _LOG_SET(fatal) 43 | 44 | #define _LOG(_severity) \ 45 | BOOST_LOG_SEV(RenderStudio::logger::get(), boost::log::trivial::_severity) \ 46 | << boost::log::add_value("Function", _FUNCTION_NAME) \ 47 | << boost::log::add_value("Line", static_cast(__LINE__)) 48 | #define LOG_TRACE _LOG(trace) 49 | #define LOG_DEBUG _LOG(debug) 50 | #define LOG_INFO _LOG(info) 51 | #define LOG_WARNING _LOG(warning) 52 | #define LOG_ERROR _LOG(error) 53 | #define LOG_FATAL _LOG(fatal) 54 | -------------------------------------------------------------------------------- /Sources/Networking/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | set(KIT_TARGET_NAME "RenderStudioNetworking") 17 | 18 | set(CMAKE_CXX_STANDARD 20) 19 | 20 | # Create target 21 | file(GLOB SOURCES *.h *.cpp) 22 | 23 | if (NOT WIN32) 24 | list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Certificates.h) 25 | list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Certificates.cpp) 26 | endif() 27 | 28 | add_library(${KIT_TARGET_NAME} STATIC ${SOURCES}) 29 | 30 | if (WIN32) 31 | find_package(BinaryOpenSSL REQUIRED) 32 | target_compile_options(${KIT_TARGET_NAME} PRIVATE /bigobj) 33 | endif() 34 | 35 | # Link libraries 36 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 37 | Boost::boost 38 | OpenSSL::SSL 39 | uriparser 40 | fmt::fmt 41 | RenderStudioLogger 42 | RenderStudioUtils 43 | RenderStudioNotice 44 | $ 45 | ) 46 | 47 | if (TBB_INCLUDE_DIR) 48 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ${TBB_INCLUDE_DIR}) 49 | endif() 50 | 51 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ..) 52 | 53 | if(WIN32) 54 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE Crypt32) 55 | endif() 56 | 57 | if(MSVC AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") 58 | target_compile_options(${KIT_TARGET_NAME} PRIVATE /bigobj) 59 | endif() 60 | 61 | # Install headers 62 | install(FILES WebsocketClient.h RestClient.h MaterialLibraryApi.h Url.h Certificates.h WebsocketServer.h 63 | DESTINATION include/RenderStudio/Networking) 64 | 65 | install(FILES ${OPENSSL_SSL_BINARY} ${OPENSSL_CRYPTO_BINARY} 66 | DESTINATION lib) 67 | 68 | SetDefaultCompileDefinitions(${KIT_TARGET_NAME}) 69 | SetMaxWarningLevel(${KIT_TARGET_NAME}) 70 | -------------------------------------------------------------------------------- /Sources/Networking/Certificates.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Certificates.h" 16 | 17 | #pragma warning(push, 0) 18 | #ifdef _WIN32 19 | #include 20 | #elif __linux__ 21 | #error "Linux certificate loading not implemented" 22 | #endif 23 | #pragma warning(pop) 24 | 25 | namespace RenderStudio::Networking 26 | { 27 | 28 | void 29 | AddWindowsRootCertificatesFromStores(boost::asio::ssl::context& ctx, const std::vector& storeNames) 30 | { 31 | X509_STORE* store = X509_STORE_new(); 32 | 33 | for (const std::string& storeName : storeNames) 34 | { 35 | HCERTSTORE hStore = CertOpenSystemStore(0, storeName.c_str()); 36 | if (hStore == NULL) 37 | { 38 | return; 39 | } 40 | 41 | PCCERT_CONTEXT pContext = NULL; 42 | while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) 43 | { 44 | // convert from DER to internal format 45 | X509* x509 = d2i_X509(NULL, (const unsigned char**)&pContext->pbCertEncoded, pContext->cbCertEncoded); 46 | if (x509 != NULL) 47 | { 48 | X509_STORE_add_cert(store, x509); 49 | X509_free(x509); 50 | } 51 | } 52 | 53 | CertFreeCertificateContext(pContext); 54 | CertCloseStore(hStore, 0); 55 | } 56 | 57 | // attach X509_STORE to boost ssl context 58 | SSL_CTX_set_cert_store(ctx.native_handle(), store); 59 | } 60 | 61 | void 62 | AddWindowsRootCertificates(boost::asio::ssl::context& ctx) 63 | { 64 | AddWindowsRootCertificatesFromStores(ctx, { "ROOT", "CA" }); 65 | } 66 | 67 | } // namespace RenderStudio::Networking 68 | -------------------------------------------------------------------------------- /Sources/Networking/Certificates.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | 21 | #include 22 | #pragma warning(pop) 23 | 24 | namespace RenderStudio::Networking 25 | { 26 | 27 | void AddWindowsRootCertificatesFromStores(boost::asio::ssl::context& ctx, const std::vector& storeNames); 28 | void AddWindowsRootCertificates(boost::asio::ssl::context& ctx); 29 | 30 | } // namespace RenderStudio::Networking 31 | -------------------------------------------------------------------------------- /Sources/Networking/LocalStorageApi.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "MaterialLibraryApi.h" 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | 20 | #include 21 | #include 22 | #pragma warning(pop) 23 | 24 | #include "LocalStorageApi.h" 25 | #include "RestClient.h" 26 | 27 | #include 28 | #include 29 | 30 | namespace RenderStudio::Networking::LocalStorageAPI 31 | { 32 | 33 | /// 34 | /// Structure parsing 35 | /// 36 | 37 | template 38 | void 39 | Extract(boost::json::object const& json, T& t, boost::json::string_view key) 40 | { 41 | t = boost::json::value_to(json.at(key)); 42 | } 43 | 44 | template 45 | void 46 | Extract(boost::json::object const& json, std::optional& t, boost::json::string_view key) 47 | { 48 | if (json.if_contains(key) && !json.at(key).is_null()) 49 | { 50 | t = boost::json::value_to(json.at(key)); 51 | } 52 | } 53 | 54 | PackageResponse 55 | tag_invoke(boost::json::value_to_tag, boost::json::value const& json) 56 | { 57 | PackageResponse r; 58 | const boost::json::object& root = json.as_object(); 59 | 60 | Extract(root, r.count, "count"); 61 | Extract(root, r.results, "results"); 62 | 63 | return r; 64 | } 65 | 66 | PackageResponse::Item 67 | tag_invoke(boost::json::value_to_tag, boost::json::value const& json) 68 | { 69 | PackageResponse::Item r; 70 | const boost::json::object& root = json.as_object(); 71 | 72 | Extract(root, r.created_at, "created_at"); 73 | Extract(root, r.updated_at, "updated_at"); 74 | Extract(root, r.id, "id"); 75 | Extract(root, r.name, "name"); 76 | Extract(root, r.type, "type"); 77 | Extract(root, r.file, "file"); 78 | Extract(root, r.thumbnail, "thumbnail"); 79 | Extract(root, r.texture, "texture"); 80 | 81 | return r; 82 | } 83 | 84 | /// 85 | /// Network requests 86 | /// 87 | 88 | PackageResponse::Item 89 | GetLightPackage(const std::string& lightId, const std::string& storageUrl) 90 | { 91 | std::string response 92 | = RenderStudio::Networking::RestClient().Get(fmt::format("{}/api/lights/{}", storageUrl, lightId)); 93 | 94 | boost::json::error_code ec; 95 | boost::json::value json = boost::json::parse(response, ec); 96 | 97 | return boost::json::value_to(json); 98 | } 99 | 100 | std::filesystem::path 101 | Download(const PackageResponse::Item& package, const std::filesystem::path& path, const std::string& storageUrl) 102 | { 103 | auto getUsdRoot = [&]() 104 | { 105 | for (auto const& entry : std::filesystem::recursive_directory_iterator(path)) 106 | { 107 | if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ".usda") 108 | { 109 | return entry.path(); 110 | } 111 | } 112 | 113 | throw std::runtime_error("Can't find USDA file after download"); 114 | }; 115 | 116 | if (storageUrl.empty()) 117 | { 118 | throw std::runtime_error("Storage URL was empty"); 119 | } 120 | 121 | // Skip downloading if exists 122 | if (std::filesystem::exists(path)) 123 | { 124 | return getUsdRoot(); 125 | } 126 | else 127 | { 128 | std::filesystem::create_directories(path); 129 | } 130 | 131 | // Download light USDA file 132 | RenderStudio::Utils::TempDirectory temp; 133 | std::filesystem::path usdaPath = temp.Path() / package.file; 134 | RenderStudio::Networking::RestClient().Download(storageUrl + "/api/lights/" + package.id + "/file", usdaPath); 135 | std::filesystem::rename(usdaPath, path / package.file); 136 | 137 | // Download light texture 138 | if (package.texture.has_value()) 139 | { 140 | std::filesystem::path texturePath = temp.Path() / package.file; 141 | RenderStudio::Networking::RestClient().Download( 142 | storageUrl + "/api/lights/" + package.id + "/texture", texturePath); 143 | std::filesystem::rename(texturePath, path / package.texture.value()); 144 | } 145 | 146 | return getUsdRoot(); 147 | } 148 | 149 | } // namespace RenderStudio::Networking::LocalStorageAPI 150 | -------------------------------------------------------------------------------- /Sources/Networking/LocalStorageApi.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #pragma warning(pop) 24 | 25 | namespace RenderStudio::Networking::LocalStorageAPI 26 | { 27 | 28 | /// 29 | /// Structures 30 | /// 31 | 32 | struct PackageResponse 33 | { 34 | struct Item 35 | { 36 | std::string created_at; 37 | std::string updated_at; 38 | std::string id; 39 | std::string name; 40 | std::string type; 41 | std::string file; 42 | std::string thumbnail; 43 | std::optional texture; 44 | }; 45 | 46 | std::uint32_t count; 47 | std::vector results; 48 | }; 49 | 50 | /// 51 | /// Structure parsing 52 | /// 53 | 54 | PackageResponse tag_invoke(boost::json::value_to_tag, boost::json::value const& json); 55 | PackageResponse::Item tag_invoke(boost::json::value_to_tag, boost::json::value const& json); 56 | 57 | /// 58 | /// Network requests 59 | /// 60 | 61 | PackageResponse::Item GetLightPackage(const std::string& lightId, const std::string& storageUrl); 62 | std::filesystem::path 63 | Download(const PackageResponse::Item& package, const std::filesystem::path& path, const std::string& storageUrl); 64 | 65 | } // namespace RenderStudio::Networking::LocalStorageAPI 66 | -------------------------------------------------------------------------------- /Sources/Networking/MaterialLibraryApi.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "MaterialLibraryApi.h" 16 | 17 | #include "RestClient.h" 18 | 19 | #pragma warning(push, 0) 20 | #include 21 | 22 | #include 23 | #pragma warning(pop) 24 | 25 | #include 26 | #include 27 | 28 | namespace RenderStudio::Networking::MaterialLibraryAPI 29 | { 30 | 31 | /// 32 | /// Network requests 33 | /// 34 | 35 | PackageResponse 36 | GetMaterialPackage(const std::string& materialId) 37 | { 38 | std::string response = RenderStudio::Networking::RestClient().Get( 39 | "https://api.matlib.gpuopen.com/api/packages/?material=" + materialId); 40 | 41 | boost::json::error_code ec; 42 | boost::json::value json = boost::json::parse(response, ec); 43 | 44 | return boost::json::value_to(json); 45 | } 46 | 47 | std::filesystem::path 48 | Download(const PackageResponse::Item& material, const std::filesystem::path& path) 49 | { 50 | auto getMtlxRoot = [&]() 51 | { 52 | for (auto const& entry : std::filesystem::recursive_directory_iterator(path)) 53 | { 54 | if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ".mtlx") 55 | { 56 | return entry.path(); 57 | } 58 | } 59 | 60 | throw std::runtime_error("Can't find MaterialX file after download"); 61 | }; 62 | 63 | // Skip downloading if exists 64 | if (std::filesystem::exists(path)) 65 | { 66 | return getMtlxRoot(); 67 | } 68 | else 69 | { 70 | std::filesystem::create_directories(path); 71 | } 72 | 73 | // Download and extract archive 74 | RenderStudio::Utils::TempDirectory temp; 75 | std::filesystem::path archivePath = temp.Path() / "Package.zip"; 76 | RenderStudio::Networking::RestClient().Download(material.file_url, archivePath); 77 | RenderStudio::Utils::Extract(archivePath, temp.Path() / "Package"); 78 | RenderStudio::Utils::Move(temp.Path() / "Package", path); 79 | 80 | // Return file name 81 | return getMtlxRoot(); 82 | } 83 | 84 | /// 85 | /// Structure parsing 86 | /// 87 | 88 | template 89 | void 90 | Extract(boost::json::object const& json, T& t, boost::json::string_view key) 91 | { 92 | t = boost::json::value_to(json.at(key)); 93 | } 94 | 95 | PackageResponse 96 | tag_invoke(boost::json::value_to_tag, boost::json::value const& json) 97 | { 98 | PackageResponse r; 99 | const boost::json::object& root = json.as_object(); 100 | 101 | Extract(root, r.count, "count"); 102 | Extract(root, r.results, "results"); 103 | 104 | return r; 105 | } 106 | 107 | PackageResponse::Item 108 | tag_invoke(boost::json::value_to_tag, boost::json::value const& json) 109 | { 110 | PackageResponse::Item r; 111 | const boost::json::object& root = json.as_object(); 112 | 113 | Extract(root, r.id, "id"); 114 | Extract(root, r.author, "author"); 115 | Extract(root, r.file_url, "file_url"); 116 | Extract(root, r.created_date, "created_date"); 117 | Extract(root, r.updated_date, "updated_date"); 118 | Extract(root, r.file, "file"); 119 | Extract(root, r.label, "label"); 120 | 121 | // Convert size from string "14.1 MB" to float 14.1 122 | std::string size_in = boost::json::value_to(json.at("size")); 123 | std::vector tokens; 124 | boost::split(tokens, size_in, boost::is_any_of(" ")); 125 | 126 | if (tokens.size() != 2) 127 | { 128 | throw std::runtime_error("Wrong tokens count in deserializing size"); 129 | } 130 | 131 | float size = std::stof(tokens.at(0)); 132 | 133 | if (tokens.at(1) == "MB") 134 | { 135 | size *= 1; 136 | } 137 | else if (tokens.at(1) == "KB") 138 | { 139 | size /= 1024; 140 | } 141 | else if (tokens.at(1) == "GB") 142 | { 143 | size *= 1024; 144 | } 145 | else 146 | { 147 | throw std::runtime_error("Wrong size token in deserializing size"); 148 | } 149 | 150 | r.size_mb = size; 151 | 152 | return r; 153 | } 154 | 155 | } // namespace RenderStudio::Networking::MaterialLibraryAPI 156 | -------------------------------------------------------------------------------- /Sources/Networking/MaterialLibraryApi.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | 21 | #include 22 | #pragma warning(pop) 23 | 24 | namespace RenderStudio::Networking::MaterialLibraryAPI 25 | { 26 | 27 | /// 28 | /// Structures 29 | /// 30 | 31 | struct PackageResponse 32 | { 33 | struct Item 34 | { 35 | std::string id; 36 | std::string author; 37 | std::string file_url; 38 | float size_mb; 39 | std::string created_date; 40 | std::string updated_date; 41 | std::string file; 42 | std::string label; 43 | }; 44 | 45 | std::uint32_t count; 46 | std::vector results; 47 | }; 48 | 49 | /// 50 | /// Structure parsing 51 | /// 52 | 53 | PackageResponse tag_invoke(boost::json::value_to_tag, boost::json::value const& json); 54 | PackageResponse::Item tag_invoke(boost::json::value_to_tag, boost::json::value const& json); 55 | 56 | /// 57 | /// Network requests 58 | /// 59 | 60 | PackageResponse GetMaterialPackage(const std::string& materialId); 61 | std::filesystem::path Download(const PackageResponse::Item& material, const std::filesystem::path& path); 62 | 63 | } // namespace RenderStudio::Networking::MaterialLibraryAPI 64 | -------------------------------------------------------------------------------- /Sources/Networking/RestClient.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #pragma warning(pop) 24 | 25 | #include "Url.h" 26 | 27 | namespace RenderStudio::Networking 28 | { 29 | 30 | class RestClient 31 | { 32 | public: 33 | std::string Get(const std::string& request); 34 | std::string Post(const std::string& request, const std::string& body); 35 | std::string Put(const std::string& request, const std::string& body); 36 | void Download(const std::string& request, const std::filesystem::path& location); 37 | 38 | enum class Parameters 39 | { 40 | ContentType, 41 | Authorization 42 | }; 43 | 44 | RestClient() = default; 45 | RestClient(const std::map& parameters); 46 | 47 | private: 48 | boost::asio::io_context mIoContext; 49 | std::map mParameters; 50 | }; 51 | 52 | } // namespace RenderStudio::Networking 53 | -------------------------------------------------------------------------------- /Sources/Networking/Url.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Url.h" 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #pragma warning(pop) 24 | 25 | #include 26 | 27 | namespace RenderStudio::Networking 28 | { 29 | 30 | Url 31 | Url::Parse(const std::string& request) 32 | { 33 | UriUriA uri; 34 | const char* errorPos; 35 | 36 | if (uriParseSingleUriA(&uri, request.c_str(), &errorPos) != URI_SUCCESS) 37 | { 38 | throw std::runtime_error("Can't parse URL: " + request); 39 | } 40 | 41 | Url result {}; 42 | 43 | // Parse basic fields 44 | result.mProtocol = std::string(uri.scheme.first, uri.scheme.afterLast); 45 | result.mHost = std::string(uri.hostText.first, uri.hostText.afterLast); 46 | result.mPort = std::string(uri.portText.first, uri.portText.afterLast); 47 | 48 | // Parse full path 49 | auto current = uri.pathHead; 50 | while (current != nullptr) 51 | { 52 | result.mPath += "/" + std::string { current->text.first, current->text.afterLast }; 53 | current = current->next; 54 | } 55 | 56 | // Parse full query 57 | std::string query = std::string(uri.query.first, uri.query.afterLast); 58 | std::string key, value; 59 | std::istringstream ss(query); 60 | while (std::getline(ss, key, '=') && std::getline(ss, value, '&')) 61 | { 62 | result.mQuery[key] = RenderStudio::Networking::Url::Decode(value); 63 | } 64 | 65 | // Parse target = path + query 66 | result.mTarget = result.mPath; 67 | 68 | if (!query.empty()) 69 | { 70 | result.mTarget += "?" + query; 71 | } 72 | 73 | // Set port from protocol 74 | if (result.mPort.empty()) 75 | { 76 | if (result.mProtocol == "https" || result.mProtocol == "wss" || result.mProtocol == "gpuopen") 77 | { 78 | result.mPort = "443"; 79 | } 80 | else if (result.mProtocol == "http" || result.mProtocol == "ws") 81 | { 82 | result.mPort = "80"; 83 | } 84 | else 85 | { 86 | throw std::runtime_error("Unsupported protocol: " + result.mProtocol); 87 | } 88 | } 89 | 90 | // Determine SSL 91 | result.mSsl = result.mPort == "443"; 92 | 93 | uriFreeUriMembersA(&uri); 94 | return result; 95 | } 96 | 97 | std::string 98 | Url::Encode(const std::string& url) 99 | { 100 | std::string result = url; 101 | boost::replace_all(result, " ", "%20"); 102 | return result; 103 | } 104 | 105 | std::string 106 | Url::Decode(const std::string& url) 107 | { 108 | std::string result = url; 109 | boost::replace_all(result, "%20", " "); 110 | return result; 111 | } 112 | 113 | std::ostream& 114 | operator<<(std::ostream& os, const Url& url) 115 | { 116 | os << "(" << url.Protocol() << ", " << url.Host() << ", " << url.Port() << ", " << url.Target() << ", " << url.Ssl() 117 | << ")\n"; 118 | return os; 119 | } 120 | 121 | } // namespace RenderStudio::Networking 122 | -------------------------------------------------------------------------------- /Sources/Networking/Url.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | #pragma warning(pop) 21 | 22 | namespace RenderStudio::Networking 23 | { 24 | 25 | class Url 26 | { 27 | public: 28 | static Url Parse(const std::string& request); 29 | std::string Protocol() const { return mProtocol; } 30 | std::string Host() const { return mHost; } 31 | std::string Port() const { return mPort; } 32 | std::string Target() const { return mTarget; } 33 | std::string Path() const { return mPath; } 34 | const std::map& Query() const { return mQuery; } 35 | bool Ssl() const { return mSsl; } 36 | friend std::ostream& operator<<(std::ostream& os, const Url& url); 37 | 38 | static std::string Encode(const std::string& url); 39 | static std::string Decode(const std::string& url); 40 | 41 | private: 42 | std::string mProtocol; 43 | std::string mHost; 44 | std::string mPort; 45 | std::string mTarget; 46 | std::string mPath; 47 | std::map mQuery; 48 | bool mSsl; 49 | }; 50 | 51 | } // namespace RenderStudio::Networking 52 | -------------------------------------------------------------------------------- /Sources/Networking/WebsocketClient.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #pragma warning(pop) 34 | 35 | #include "Url.h" 36 | 37 | namespace boost::beast 38 | { 39 | template class ssl_stream; 40 | } 41 | 42 | namespace boost::asio::ssl 43 | { 44 | class context; 45 | } 46 | 47 | namespace RenderStudio::Networking 48 | { 49 | 50 | struct IClientLogic 51 | { 52 | virtual void OnConnected() = 0; 53 | virtual void OnDisconnected() = 0; 54 | virtual void OnMessage(const std::string& message) = 0; 55 | virtual ~IClientLogic() = default; 56 | }; 57 | 58 | class WebsocketClient : public std::enable_shared_from_this 59 | { 60 | public: 61 | template static std::shared_ptr Create(Args&&... args) 62 | { 63 | return std::shared_ptr { new WebsocketClient { std::forward(args)... } }; 64 | } 65 | 66 | ~WebsocketClient(); 67 | 68 | std::future Connect(const Url& endpoint); 69 | std::future Disconnect(); 70 | void Send(const std::string& message); 71 | static bool IsPortInUse(std::uint16_t port); 72 | 73 | private: 74 | explicit WebsocketClient(IClientLogic& logic); 75 | 76 | void Ping(boost::beast::error_code ec); 77 | void OnResolve( 78 | std::shared_ptr> promise, 79 | boost::beast::error_code ec, 80 | boost::asio::ip::tcp::resolver::results_type results); 81 | void OnConnect( 82 | std::shared_ptr> promise, 83 | boost::beast::error_code ec, 84 | boost::asio::ip::tcp::resolver::endpoint_type endpoint); 85 | void OnHandshake(std::shared_ptr> promise, boost::beast::error_code ec); 86 | void OnSslHandshake(std::shared_ptr> promise, boost::beast::error_code ec); 87 | void OnPing(boost::beast::error_code ec); 88 | void Write(const std::string& message); 89 | void OnWrite(boost::beast::error_code ec, std::size_t transferred); 90 | void OnRead(boost::beast::error_code ec, std::size_t transferred); 91 | void OnClose(std::shared_ptr> promise, boost::beast::error_code ec); 92 | 93 | private: 94 | Url mEndpoint; 95 | boost::asio::io_context mIoContext; 96 | boost::asio::ip::tcp::resolver mTcpResolver; 97 | 98 | using SslStream = boost::beast::websocket::stream>; 99 | using TcpStream = boost::beast::websocket::stream; 100 | 101 | std::variant, std::shared_ptr> mWebsocketStream; 102 | std::shared_ptr mSslContext; 103 | boost::beast::flat_buffer mReadBuffer; 104 | boost::asio::deadline_timer mPingTimer; 105 | std::thread mThread; 106 | bool mConnected; 107 | std::string mSslHost; 108 | 109 | std::queue mWriteQueue; 110 | IClientLogic& mLogic; 111 | }; 112 | 113 | } // namespace RenderStudio::Networking 114 | -------------------------------------------------------------------------------- /Sources/Networking/WebsocketServer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #pragma warning(pop) 25 | 26 | namespace RenderStudio::Networking 27 | { 28 | 29 | class WebsocketSession; 30 | class WebsocketServer; 31 | 32 | struct IServerLogic 33 | { 34 | virtual void OnConnected(std::shared_ptr session) = 0; 35 | virtual void OnDisconnected(std::shared_ptr session) = 0; 36 | virtual void OnMessage(std::shared_ptr session, const std::string& message) = 0; 37 | virtual ~IServerLogic() = default; 38 | }; 39 | 40 | class HttpSession : public std::enable_shared_from_this 41 | { 42 | explicit HttpSession(boost::asio::ip::tcp::socket&& socket, IServerLogic& logic); 43 | 44 | public: 45 | template static std::shared_ptr Create(Args&&... args) 46 | { 47 | return std::shared_ptr { new HttpSession { std::forward(args)... } }; 48 | } 49 | 50 | private: 51 | void Run(); 52 | void OnRun(); 53 | void Read(); 54 | void OnRead(boost::beast::error_code ec, std::size_t transferred); 55 | 56 | private: 57 | friend class WebsocketServer; 58 | 59 | boost::beast::tcp_stream mTcpStream; 60 | boost::optional> mParser; 61 | boost::beast::flat_buffer mBuffer; 62 | IServerLogic& mServerLogic; 63 | }; 64 | 65 | class WebsocketSession : public std::enable_shared_from_this 66 | { 67 | explicit WebsocketSession( 68 | boost::asio::ip::tcp::socket&& socket, 69 | IServerLogic& logic, 70 | boost::beast::http::message request); 71 | 72 | public: 73 | template static std::shared_ptr Create(Args&&... args) 74 | { 75 | return std::shared_ptr { new WebsocketSession { std::forward(args)... } }; 76 | } 77 | 78 | void Send(const std::string& message); 79 | 80 | std::string GetDebugName() const; 81 | std::string GetChannel() const; 82 | 83 | private: 84 | friend class HttpSession; 85 | 86 | void Run(); 87 | void OnRun(); 88 | void OnAccept(boost::beast::error_code ec); 89 | void Read(); 90 | void OnRead(boost::beast::error_code ec, std::size_t transferred); 91 | void Write(const std::string& message); 92 | void OnWrite(boost::beast::error_code ec, std::size_t transferred); 93 | 94 | private: 95 | boost::beast::websocket::stream mWebsocketStream; 96 | boost::beast::flat_buffer mReadBuffer; 97 | std::string mDebugName; 98 | IServerLogic& mServerLogic; 99 | boost::beast::http::message mRequest; 100 | std::string mChannel; 101 | std::queue mWriteQueue; 102 | bool mConnected = false; 103 | }; 104 | 105 | class WebsocketServer : public std::enable_shared_from_this 106 | { 107 | explicit WebsocketServer( 108 | boost::asio::io_context& ioc, 109 | boost::asio::ip::tcp::endpoint endpoint, 110 | IServerLogic& logic); 111 | 112 | public: 113 | template static std::shared_ptr Create(Args&&... args) 114 | { 115 | return std::shared_ptr { new WebsocketServer { std::forward(args)... } }; 116 | } 117 | 118 | void Run(); 119 | 120 | private: 121 | void Accept(); 122 | void OnAccept(boost::beast::error_code ec, boost::asio::ip::tcp::socket socket); 123 | 124 | boost::asio::io_context& mIoContext; 125 | boost::asio::ip::tcp::endpoint mTcpEndpoint; 126 | boost::asio::ip::tcp::acceptor mTcpAcceptor; 127 | IServerLogic& mServerLogic; 128 | }; 129 | 130 | } // namespace RenderStudio::Networking 131 | -------------------------------------------------------------------------------- /Sources/Networking/Workspace.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | #include "WebsocketClient.h" 24 | 25 | #include 26 | 27 | namespace RenderStudio::Networking 28 | { 29 | 30 | class Logic : public IClientLogic 31 | { 32 | public: 33 | virtual void OnConnected() override; 34 | virtual void OnDisconnected() override; 35 | virtual void OnMessage(const std::string& message) override; 36 | }; 37 | 38 | class Workspace 39 | { 40 | public: 41 | static void Connect(RenderStudio::Kit::Role role); 42 | static void Disconnect(); 43 | static void WaitIdle(); 44 | static void Pause(); 45 | static void Resume(); 46 | static bool IsIdle(); 47 | static bool IsConnected(); 48 | static void SetWorkspacePath(const std::string& path); 49 | static void SetWorkspaceUrl(const std::string& url); 50 | static std::string GetWorkspaceUrl(); 51 | 52 | private: 53 | // Configuration 54 | static inline std::filesystem::path sWorkspacePath; 55 | static inline std::string sWorkspaceUrl; 56 | 57 | // Connection 58 | static inline std::shared_ptr sClient; 59 | static inline std::shared_ptr sPingTask; 60 | 61 | // Process utils 62 | static bool LaunchWorkspace(); 63 | 64 | // State getters data 65 | static inline std::mutex sStateMutex; 66 | static inline std::condition_variable sStateConditionVariable; 67 | static inline std::string sLastState = ""; 68 | 69 | // Paused getters data 70 | static inline std::mutex sPausedMutex; 71 | static inline std::condition_variable sPausedConditionVariable; 72 | static inline bool sPaused = false; 73 | 74 | static inline bool sConnected = false; 75 | static inline Logic sLogic; 76 | 77 | friend class Logic; 78 | }; 79 | 80 | } // namespace RenderStudio::Networking 81 | -------------------------------------------------------------------------------- /Sources/Notice/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | set(KIT_TARGET_NAME "RenderStudioNotice") 17 | set(CMAKE_CXX_STANDARD 20) 18 | 19 | # Create target 20 | file(GLOB SOURCES *.h *.cpp) 21 | add_library(${KIT_TARGET_NAME} SHARED ${SOURCES}) 22 | 23 | # Link libraries 24 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 25 | $ 26 | RenderStudioLogger 27 | RenderStudioUtils 28 | ) 29 | 30 | if (MAYA_SUPPORT) 31 | cmake_policy(SET CMP0079 NEW) 32 | 33 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 34 | ${PYTHON_LIBRARIES} 35 | ) 36 | endif() 37 | 38 | if (TBB_INCLUDE_DIR) 39 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE ${TBB_LIBRARY}) 40 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ${TBB_INCLUDE_DIR}) 41 | endif() 42 | 43 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ..) 44 | target_compile_definitions(${KIT_TARGET_NAME} PRIVATE AR_EXPORTS) 45 | 46 | SetDefaultCompileDefinitions(${KIT_TARGET_NAME}) 47 | SetMaxWarningLevel(${KIT_TARGET_NAME}) 48 | 49 | # Install headers 50 | install(FILES Notice.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/RenderStudio/Notice) 51 | 52 | # Install library 53 | install(TARGETS ${KIT_TARGET_NAME} DESTINATION lib) 54 | -------------------------------------------------------------------------------- /Sources/Notice/Notice.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Notice.h" 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | #pragma warning(pop) 21 | 22 | #include 23 | #include 24 | 25 | PXR_NAMESPACE_OPEN_SCOPE 26 | 27 | TF_INSTANTIATE_TYPE(RenderStudioNotice::PrimitiveChanged, TfType::CONCRETE, TF_1_PARENT(TfNotice)) 28 | TF_INSTANTIATE_TYPE(RenderStudioNotice::LiveHistoryStatus, TfType::CONCRETE, TF_1_PARENT(TfNotice)) 29 | TF_INSTANTIATE_TYPE(RenderStudioNotice::OwnerChanged, TfType::CONCRETE, TF_1_PARENT(TfNotice)) 30 | TF_INSTANTIATE_TYPE(RenderStudioNotice::WorkspaceState, TfType::CONCRETE, TF_1_PARENT(TfNotice)) 31 | TF_INSTANTIATE_TYPE(RenderStudioNotice::FileUpdated, TfType::CONCRETE, TF_1_PARENT(TfNotice)) 32 | TF_INSTANTIATE_TYPE(RenderStudioNotice::WorkspaceConnectionChanged, TfType::CONCRETE, TF_1_PARENT(TfNotice)) 33 | TF_INSTANTIATE_TYPE(RenderStudioNotice::LiveConnectionChanged, TfType::CONCRETE, TF_1_PARENT(TfNotice)) 34 | TF_INSTANTIATE_TYPE(RenderStudioNotice::LayerReloaded, TfType::CONCRETE, TF_1_PARENT(TfNotice)) 35 | 36 | RenderStudioNotice::PrimitiveChanged::PrimitiveChanged(const SdfPath& path, bool resynced) 37 | : mChangedPrim(path) 38 | , mWasResynched(resynced) 39 | { 40 | if (!mChangedPrim.IsPrimPath()) 41 | { 42 | mChangedPrim = mChangedPrim.GetPrimPath(); 43 | } 44 | 45 | if (!mChangedPrim.IsPrimPath() || mChangedPrim.IsAbsoluteRootPath()) 46 | { 47 | mIsValid = false; 48 | } 49 | } 50 | 51 | SdfPath 52 | RenderStudioNotice::PrimitiveChanged::GetChangedPrim() const 53 | { 54 | return mChangedPrim; 55 | } 56 | 57 | bool 58 | RenderStudioNotice::PrimitiveChanged::WasResynched() const 59 | { 60 | return mWasResynched; 61 | } 62 | 63 | bool 64 | RenderStudioNotice::PrimitiveChanged::IsValid() const 65 | { 66 | return mIsValid; 67 | } 68 | 69 | RenderStudioNotice::LiveHistoryStatus::LiveHistoryStatus(const std::string& name, const std::string& category) 70 | : mName(name) 71 | , mCategory(category) 72 | , mUuid(RenderStudio::Utils::GenerateUUID()) 73 | { 74 | mAction = RenderStudioNotice::LiveHistoryStatus::Action::Started; 75 | Send(); 76 | } 77 | 78 | RenderStudioNotice::LiveHistoryStatus::~LiveHistoryStatus() 79 | { 80 | mAction = RenderStudioNotice::LiveHistoryStatus::Action::Finished; 81 | Send(); 82 | } 83 | 84 | std::string 85 | RenderStudioNotice::LiveHistoryStatus::GetName() const 86 | { 87 | return mName; 88 | } 89 | 90 | std::string 91 | RenderStudioNotice::LiveHistoryStatus::GetCategory() const 92 | { 93 | return mCategory; 94 | } 95 | 96 | std::string 97 | RenderStudioNotice::LiveHistoryStatus::GetUuid() const 98 | { 99 | return mUuid; 100 | } 101 | 102 | RenderStudioNotice::LiveHistoryStatus::Action 103 | RenderStudioNotice::LiveHistoryStatus::GetAction() const 104 | { 105 | return mAction; 106 | } 107 | 108 | RenderStudioNotice::OwnerChanged::OwnerChanged(const SdfPath& path, const std::optional owner) 109 | : mPath(path) 110 | , mOwner(owner) 111 | { 112 | } 113 | 114 | SdfPath 115 | RenderStudioNotice::OwnerChanged::GetPath() const 116 | { 117 | return mPath; 118 | } 119 | 120 | std::optional 121 | RenderStudioNotice::OwnerChanged::GetOwner() const 122 | { 123 | return mOwner; 124 | } 125 | 126 | RenderStudioNotice::WorkspaceState::WorkspaceState(RenderStudioNotice::WorkspaceState::State state) 127 | : mState(state) 128 | { 129 | } 130 | 131 | RenderStudioNotice::WorkspaceState::WorkspaceState(const std::string& state) 132 | { 133 | static std::map states { 134 | { "idle", State::Idle }, 135 | { "syncing", State::Syncing }, 136 | { "error", State::Error }, 137 | }; 138 | 139 | auto it = states.find(state); 140 | 141 | if (it != states.end()) 142 | { 143 | mState = states.at(state); 144 | } 145 | else 146 | { 147 | mState = State::Other; 148 | } 149 | } 150 | 151 | RenderStudioNotice::WorkspaceState::State 152 | RenderStudioNotice::WorkspaceState::GetState() const 153 | { 154 | return mState; 155 | } 156 | 157 | RenderStudioNotice::FileUpdated::FileUpdated(const std::string& path) 158 | : mPath(path) 159 | { 160 | } 161 | 162 | std::string 163 | RenderStudioNotice::FileUpdated::GetPath() const 164 | { 165 | return mPath; 166 | } 167 | 168 | RenderStudioNotice::WorkspaceConnectionChanged::WorkspaceConnectionChanged(bool status) 169 | : mStatus(status) 170 | { 171 | } 172 | 173 | bool 174 | RenderStudioNotice::WorkspaceConnectionChanged::IsConnected() const 175 | { 176 | return mStatus; 177 | } 178 | 179 | RenderStudioNotice::LiveConnectionChanged::LiveConnectionChanged(bool status) 180 | : mStatus(status) 181 | { 182 | } 183 | 184 | bool 185 | RenderStudioNotice::LiveConnectionChanged::IsConnected() const 186 | { 187 | return mStatus; 188 | } 189 | 190 | RenderStudioNotice::LayerReloaded::LayerReloaded(const std::string& identifier) 191 | : mIdentifier(identifier) 192 | { 193 | } 194 | 195 | std::string 196 | RenderStudioNotice::LayerReloaded::GetIdentifier() const 197 | { 198 | return mIdentifier; 199 | } 200 | 201 | PXR_NAMESPACE_CLOSE_SCOPE 202 | -------------------------------------------------------------------------------- /Sources/Notice/Notice.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #pragma warning(pop) 25 | 26 | PXR_NAMESPACE_OPEN_SCOPE 27 | 28 | class RenderStudioNotice 29 | { 30 | public: 31 | class PrimitiveChanged : public TfNotice 32 | { 33 | public: 34 | AR_API 35 | PrimitiveChanged(const SdfPath& path, bool resynched = false); 36 | 37 | AR_API 38 | SdfPath GetChangedPrim() const; 39 | 40 | AR_API 41 | bool WasResynched() const; 42 | 43 | AR_API 44 | bool IsValid() const; 45 | 46 | private: 47 | SdfPath mChangedPrim; 48 | bool mWasResynched = false; 49 | bool mIsValid = true; 50 | }; 51 | 52 | class LiveHistoryStatus : public TfNotice 53 | { 54 | public: 55 | enum class Action 56 | { 57 | Started, 58 | Finished 59 | }; 60 | 61 | AR_API 62 | LiveHistoryStatus(const std::string& name, const std::string& category); 63 | 64 | AR_API 65 | ~LiveHistoryStatus(); 66 | 67 | AR_API 68 | std::string GetName() const; 69 | 70 | AR_API 71 | std::string GetCategory() const; 72 | 73 | AR_API 74 | std::string GetUuid() const; 75 | 76 | AR_API 77 | Action GetAction() const; 78 | 79 | private: 80 | std::string mName; 81 | std::string mCategory; 82 | std::string mUuid; 83 | Action mAction; 84 | }; 85 | 86 | class OwnerChanged : public TfNotice 87 | { 88 | public: 89 | AR_API 90 | OwnerChanged(const SdfPath& path, const std::optional owner); 91 | 92 | AR_API 93 | SdfPath GetPath() const; 94 | 95 | AR_API 96 | std::optional GetOwner() const; 97 | 98 | private: 99 | SdfPath mPath; 100 | std::optional mOwner; 101 | }; 102 | 103 | class WorkspaceState : public TfNotice 104 | { 105 | public: 106 | enum class State 107 | { 108 | Idle, 109 | Syncing, 110 | Error, 111 | Other 112 | }; 113 | 114 | AR_API 115 | WorkspaceState(State state); 116 | 117 | AR_API 118 | WorkspaceState(const std::string& state); 119 | 120 | AR_API 121 | State GetState() const; 122 | 123 | private: 124 | State mState; 125 | }; 126 | 127 | class FileUpdated : public TfNotice 128 | { 129 | public: 130 | AR_API 131 | FileUpdated(const std::string& path); 132 | 133 | AR_API 134 | std::string GetPath() const; 135 | 136 | private: 137 | std::string mPath; 138 | }; 139 | 140 | class WorkspaceConnectionChanged : public TfNotice 141 | { 142 | public: 143 | AR_API 144 | WorkspaceConnectionChanged(bool status); 145 | 146 | AR_API 147 | bool IsConnected() const; 148 | 149 | private: 150 | bool mStatus; 151 | }; 152 | 153 | class LiveConnectionChanged : public TfNotice 154 | { 155 | public: 156 | AR_API 157 | LiveConnectionChanged(bool status); 158 | 159 | AR_API 160 | bool IsConnected() const; 161 | 162 | private: 163 | bool mStatus; 164 | }; 165 | 166 | class LayerReloaded : public TfNotice 167 | { 168 | public: 169 | AR_API 170 | LayerReloaded(const std::string& identifier); 171 | 172 | AR_API 173 | std::string GetIdentifier() const; 174 | 175 | private: 176 | std::string mIdentifier; 177 | }; 178 | }; 179 | 180 | PXR_NAMESPACE_CLOSE_SCOPE 181 | -------------------------------------------------------------------------------- /Sources/Resolver/Asset.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Asset.h" 16 | 17 | #include "Resolver.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | PXR_NAMESPACE_OPEN_SCOPE 24 | 25 | std::shared_ptr 26 | GpuOpenAsset::Open(const std::string& uuid, const std::filesystem::path& location) 27 | { 28 | return std::make_shared(uuid, location); 29 | } 30 | 31 | GpuOpenAsset::GpuOpenAsset(const std::string& uuid, const std::filesystem::path& location) 32 | : mUuid(uuid) 33 | { 34 | // Download material 35 | try 36 | { 37 | auto package = RenderStudio::Networking::MaterialLibraryAPI::GetMaterialPackage(uuid); 38 | auto material = *std::min_element( 39 | package.results.begin(), 40 | package.results.end(), 41 | [](const auto& a, const auto& b) { return a.size_mb < b.size_mb; }); 42 | 43 | auto mtlxRootLocation = RenderStudio::Networking::MaterialLibraryAPI::Download(material, location); 44 | mFileMapping = ArchOpenFile(mtlxRootLocation.string().c_str(), "rb"); 45 | } 46 | catch (const std::exception& ex) 47 | { 48 | LOG_FATAL << ex.what(); 49 | } 50 | } 51 | 52 | GpuOpenAsset::~GpuOpenAsset() { fclose(mFileMapping); } 53 | 54 | std::size_t 55 | GpuOpenAsset::GetSize() const 56 | { 57 | return ArchGetFileLength(mFileMapping); 58 | } 59 | 60 | std::shared_ptr 61 | GpuOpenAsset::GetBuffer() const 62 | { 63 | ArchConstFileMapping mapping = ArchMapFileReadOnly(mFileMapping); 64 | if (!mapping) 65 | { 66 | return nullptr; 67 | } 68 | 69 | struct _Deleter 70 | { 71 | explicit _Deleter(ArchConstFileMapping&& mapping) 72 | : _mapping(new ArchConstFileMapping(std::move(mapping))) 73 | { 74 | } 75 | 76 | void operator()(const char* b) 77 | { 78 | (void)b; 79 | _mapping.reset(); 80 | } 81 | 82 | std::shared_ptr _mapping; 83 | }; 84 | 85 | const char* buffer = mapping.get(); 86 | return std::shared_ptr(buffer, _Deleter(std::move(mapping))); 87 | } 88 | 89 | std::size_t 90 | GpuOpenAsset::Read(void* buffer, std::size_t count, std::size_t offset) const 91 | { 92 | std::int64_t numRead = ArchPRead(mFileMapping, buffer, count, offset); 93 | if (numRead == -1) 94 | { 95 | LOG_ERROR << "Error occurred reading file: " << ArchStrerror(); 96 | return 0; 97 | } 98 | return numRead; 99 | } 100 | 101 | std::pair 102 | GpuOpenAsset::GetFileUnsafe() const 103 | { 104 | return std::make_pair(mFileMapping, 0); 105 | } 106 | 107 | std::shared_ptr 108 | LocalStorageAsset::Open(const std::string& name, const std::filesystem::path& location) 109 | { 110 | return std::make_shared(name, location); 111 | } 112 | 113 | LocalStorageAsset::LocalStorageAsset(const std::string& name, const std::filesystem::path& location) 114 | { 115 | // Aggressive optimization here, ignoring mUuid and applying first .usda file under light directory assuming that 116 | // it's valid 117 | mUuid = "empty"; 118 | 119 | std::filesystem::path usdaLocation; 120 | 121 | if (!std::filesystem::exists(location)) 122 | { 123 | // Download light 124 | auto package = RenderStudio::Networking::LocalStorageAPI::GetLightPackage( 125 | name, RenderStudioResolver::GetLocalStorageUrl()); 126 | 127 | usdaLocation = RenderStudio::Networking::LocalStorageAPI::Download( 128 | package, location, RenderStudioResolver::GetLocalStorageUrl()); 129 | } 130 | else 131 | { 132 | for (auto const& entry : std::filesystem::recursive_directory_iterator(location)) 133 | { 134 | if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ".usda") 135 | { 136 | usdaLocation = entry.path(); 137 | break; 138 | } 139 | } 140 | 141 | if (usdaLocation.empty()) 142 | { 143 | throw std::runtime_error("Storage was corrupted, can't find " + location.string()); 144 | } 145 | } 146 | 147 | mFileMapping = ArchOpenFile(usdaLocation.string().c_str(), "rb"); 148 | } 149 | 150 | PXR_NAMESPACE_CLOSE_SCOPE 151 | -------------------------------------------------------------------------------- /Sources/Resolver/Asset.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #pragma warning(pop) 27 | 28 | #include 29 | 30 | PXR_NAMESPACE_OPEN_SCOPE 31 | 32 | class GpuOpenAsset : public ArAsset 33 | { 34 | public: 35 | AR_API 36 | static std::shared_ptr Open(const std::string& uuid, const std::filesystem::path& location); 37 | 38 | AR_API 39 | explicit GpuOpenAsset(const std::string& uuid, const std::filesystem::path& location); 40 | 41 | AR_API 42 | explicit GpuOpenAsset() = default; 43 | 44 | AR_API 45 | virtual ~GpuOpenAsset(); 46 | 47 | AR_API 48 | virtual std::size_t GetSize() const override; 49 | 50 | AR_API 51 | virtual std::shared_ptr GetBuffer() const override; 52 | 53 | AR_API 54 | virtual std::size_t Read(void* buffer, std::size_t count, std::size_t offset) const override; 55 | 56 | AR_API 57 | virtual std::pair GetFileUnsafe() const override; 58 | 59 | protected: 60 | std::string mUuid; 61 | FILE* mFileMapping; 62 | }; 63 | 64 | class LocalStorageAsset : public GpuOpenAsset 65 | { 66 | public: 67 | AR_API 68 | static std::shared_ptr Open(const std::string& name, const std::filesystem::path& location); 69 | 70 | AR_API 71 | explicit LocalStorageAsset(const std::string& name, const std::filesystem::path& location); 72 | }; 73 | 74 | PXR_NAMESPACE_CLOSE_SCOPE 75 | -------------------------------------------------------------------------------- /Sources/Resolver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | set(KIT_TARGET_NAME "RenderStudioResolver") 17 | 18 | # Create target 19 | file(GLOB SOURCES *.h *.cpp) 20 | add_library(${KIT_TARGET_NAME} SHARED ${SOURCES}) 21 | 22 | # Link libraries 23 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 24 | Boost::boost 25 | Boost::python 26 | ar 27 | sdf 28 | RenderStudioNetworking 29 | RenderStudioLogger 30 | RenderStudioSerialization 31 | RenderStudioUtils 32 | RenderStudioNotice 33 | ) 34 | 35 | if (TBB_INCLUDE_DIR) 36 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE ${TBB_LIBRARY}) 37 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ${TBB_INCLUDE_DIR}) 38 | endif() 39 | 40 | if (MAYA_SUPPORT) 41 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 42 | ${PYTHON_LIBRARIES} 43 | usd 44 | ) 45 | endif() 46 | 47 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ..) 48 | 49 | if(WIN32) 50 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 51 | wsock32 52 | ws2_32 53 | bcrypt 54 | ) 55 | endif() 56 | 57 | if (WIN32) 58 | string (REGEX REPLACE "v([0-9]+)" "\\1" VS_NUMERIC_PLATFORM_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET}) 59 | else() 60 | set(VS_NUMERIC_PLATFORM_TOOLSET 0) 61 | endif() 62 | 63 | # Set compile options 64 | SetDefaultCompileDefinitions(${KIT_TARGET_NAME}) 65 | target_compile_definitions(${KIT_TARGET_NAME} PRIVATE 66 | AR_EXPORTS 67 | VS_PLATFORM_TOOLSET=${VS_NUMERIC_PLATFORM_TOOLSET} 68 | ) 69 | 70 | SetMaxWarningLevel(${KIT_TARGET_NAME}) 71 | 72 | # Install library 73 | install(TARGETS ${KIT_TARGET_NAME} 74 | DESTINATION plugin/usd) 75 | 76 | # Install plugInfo 77 | if(WIN32) 78 | set(PLUGIN_LIBRARY_NAME ${KIT_TARGET_NAME}.dll) 79 | elseif(UNIX) 80 | set(PLUGIN_LIBRARY_NAME lib${KIT_TARGET_NAME}.so) 81 | endif() 82 | 83 | configure_file(plugInfo.json plugInfo.json @ONLY) 84 | 85 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/plugInfo.json 86 | DESTINATION plugin/usd/${KIT_TARGET_NAME}/resources) 87 | -------------------------------------------------------------------------------- /Sources/Resolver/Data.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #pragma warning(pop) 29 | 30 | #include 31 | #include 32 | 33 | PXR_NAMESPACE_OPEN_SCOPE 34 | 35 | TF_DECLARE_WEAK_AND_REF_PTRS(RenderStudioData); 36 | 37 | class RenderStudioFileFormat; 38 | 39 | class RenderStudioData : public SdfAbstractData 40 | { 41 | public: 42 | RenderStudioData(); 43 | 44 | AR_API 45 | virtual ~RenderStudioData(); 46 | 47 | /// SdfAbstractData overrides 48 | AR_API 49 | virtual bool StreamsData() const; 50 | 51 | AR_API 52 | virtual void CreateSpec(const SdfPath& path, SdfSpecType specType); 53 | AR_API 54 | virtual bool HasSpec(const SdfPath& path) const; 55 | AR_API 56 | virtual void EraseSpec(const SdfPath& path); 57 | AR_API 58 | virtual void MoveSpec(const SdfPath& oldPath, const SdfPath& newPath); 59 | AR_API 60 | virtual SdfSpecType GetSpecType(const SdfPath& path) const; 61 | 62 | AR_API 63 | virtual bool Has(const SdfPath& path, const TfToken& fieldName, SdfAbstractDataValue* value) const; 64 | AR_API 65 | virtual bool Has(const SdfPath& path, const TfToken& fieldName, VtValue* value = NULL) const; 66 | AR_API 67 | virtual bool 68 | HasSpecAndField(const SdfPath& path, const TfToken& fieldName, SdfAbstractDataValue* value, SdfSpecType* specType) 69 | const; 70 | 71 | AR_API 72 | virtual bool 73 | HasSpecAndField(const SdfPath& path, const TfToken& fieldName, VtValue* value, SdfSpecType* specType) const; 74 | 75 | AR_API 76 | virtual VtValue Get(const SdfPath& path, const TfToken& fieldName) const; 77 | AR_API 78 | virtual void Set(const SdfPath& path, const TfToken& fieldName, const VtValue& value); 79 | AR_API 80 | virtual void Set(const SdfPath& path, const TfToken& fieldName, const SdfAbstractDataConstValue& value); 81 | AR_API 82 | virtual void Erase(const SdfPath& path, const TfToken& fieldName); 83 | AR_API 84 | virtual std::vector List(const SdfPath& path) const; 85 | 86 | AR_API 87 | virtual std::set ListAllTimeSamples() const; 88 | 89 | AR_API 90 | virtual std::set ListTimeSamplesForPath(const SdfPath& path) const; 91 | 92 | AR_API 93 | virtual bool GetBracketingTimeSamples(double time, double* tLower, double* tUpper) const; 94 | 95 | AR_API 96 | virtual size_t GetNumTimeSamplesForPath(const SdfPath& path) const; 97 | 98 | AR_API 99 | virtual bool 100 | GetBracketingTimeSamplesForPath(const SdfPath& path, double time, double* tLower, double* tUpper) const; 101 | 102 | AR_API 103 | virtual bool QueryTimeSample(const SdfPath& path, double time, SdfAbstractDataValue* optionalValue) const; 104 | AR_API 105 | virtual bool QueryTimeSample(const SdfPath& path, double time, VtValue* value) const; 106 | 107 | AR_API 108 | virtual void SetTimeSample(const SdfPath& path, double time, const VtValue& value); 109 | 110 | AR_API 111 | virtual void EraseTimeSample(const SdfPath& path, double time); 112 | 113 | AR_API 114 | std::size_t GetSequence() const { return mLatestAppliedSequence; } 115 | 116 | AR_API 117 | void SetOriginalFormat(SdfFileFormatConstPtr format); 118 | 119 | AR_API 120 | SdfFileFormatConstPtr GetOriginalFormat() const { return mOriginalFormat; }; 121 | 122 | protected: 123 | // SdfAbstractData overrides 124 | AR_API 125 | virtual void _VisitSpecs(SdfAbstractDataSpecVisitor* visitor) const; 126 | 127 | private: 128 | // Backing storage for a single "spec" -- prim, property, etc. 129 | typedef std::pair _FieldValuePair; 130 | struct _SpecData 131 | { 132 | _SpecData() 133 | : specType(SdfSpecTypeUnknown) 134 | { 135 | } 136 | 137 | SdfSpecType specType; 138 | std::vector<_FieldValuePair> fields; 139 | }; 140 | 141 | // Hashtable storing _SpecData. 142 | typedef SdfPath _Key; 143 | typedef SdfPath::Hash _KeyHash; 144 | typedef TfHashMap<_Key, _SpecData, _KeyHash> _HashTable; 145 | 146 | private: 147 | void ApplyDelta( 148 | SdfLayerHandle& layer, 149 | std::vector& notices, 150 | const SdfPath& path, 151 | const TfToken& key, 152 | const VtValue& value, 153 | SdfSpecType spec); 154 | void ProcessRemoteUpdates(SdfLayerHandle& layer); 155 | void AccumulateRemoteUpdate(const _HashTable& deltas, std::size_t sequence); 156 | _HashTable FetchLocalDeltas(); 157 | void OnLoaded(); 158 | 159 | const VtValue* _GetSpecTypeAndFieldValue(const SdfPath& path, const TfToken& field, SdfSpecType* specType) const; 160 | 161 | const VtValue* _GetFieldValue(const SdfPath& path, const TfToken& field) const; 162 | 163 | VtValue* _GetMutableFieldValue(const SdfPath& path, const TfToken& field); 164 | 165 | VtValue* _GetOrCreateFieldValue(const SdfPath& path, const TfToken& field); 166 | 167 | VtValue* _GetOrCreateFieldValueDelta(const SdfPath& path, const TfToken& field); 168 | 169 | private: 170 | friend class RenderStudioFileFormat; 171 | 172 | _HashTable mData; 173 | _HashTable mLocalDeltas; 174 | 175 | SdfFileFormatConstPtr mOriginalFormat = nullptr; 176 | 177 | std::set mUnacknowledgedFields; 178 | std::mutex mRemoteMutex; 179 | std::size_t mLatestAppliedSequence = 0; 180 | std::map mRemoteDeltasQueue; 181 | bool mIsLoaded = false; 182 | bool mIsProcessingRemoteUpdates = false; 183 | }; 184 | 185 | PXR_NAMESPACE_CLOSE_SCOPE 186 | -------------------------------------------------------------------------------- /Sources/Resolver/FileFormat.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #pragma warning(pop) 28 | 29 | #include "Data.h" 30 | #include "Networking/WebsocketClient.h" 31 | #include "Registry.h" 32 | 33 | PXR_NAMESPACE_OPEN_SCOPE 34 | 35 | #define RENDER_STUDIO_FILE_FORMAT_TOKENS ((Id, "studio"))((Version, "1.0"))((Target, "usd")) 36 | 37 | #pragma warning(push, 0) 38 | TF_DECLARE_PUBLIC_TOKENS(RenderStudioFileFormatTokens, AR_API, RENDER_STUDIO_FILE_FORMAT_TOKENS); 39 | #pragma warning(pop) 40 | 41 | TF_DECLARE_WEAK_AND_REF_PTRS(RenderStudioFileFormat); 42 | 43 | class ArAsset; 44 | class Logic; 45 | 46 | class RenderStudioFileFormat 47 | : public SdfFileFormat 48 | , public RenderStudio::Networking::IClientLogic 49 | { 50 | public: 51 | AR_API 52 | SdfAbstractDataRefPtr InitData(const FileFormatArguments& args) const override; 53 | 54 | AR_API 55 | virtual SdfLayer* _InstantiateNewLayer( 56 | const SdfFileFormatConstPtr& fileFormat, 57 | const std::string& identifier, 58 | const std::string& realPath, 59 | const ArAssetInfo& assetInfo, 60 | const FileFormatArguments& args) const override; 61 | 62 | AR_API 63 | virtual bool CanRead(const std::string& file) const override; 64 | 65 | AR_API 66 | virtual bool Read(SdfLayer* layer, const std::string& resolvedPath, bool metadataOnly) const override; 67 | 68 | AR_API 69 | virtual bool WriteToFile( 70 | const SdfLayer& layer, 71 | const std::string& filePath, 72 | const std::string& comment = std::string(), 73 | const FileFormatArguments& args = FileFormatArguments()) const override; 74 | 75 | // IClientLogic implementation 76 | virtual void OnConnected() override; 77 | virtual void OnDisconnected() override; 78 | virtual void OnMessage(const std::string& message) override; 79 | 80 | private: 81 | SDF_FILE_FORMAT_FACTORY_ACCESS; 82 | 83 | RenderStudioFileFormat(); 84 | virtual ~RenderStudioFileFormat(); 85 | 86 | bool ProcessLiveUpdates(); 87 | void Connect(const std::string& url); 88 | void Disconnect(); 89 | RenderStudioDataPtr _GetRenderStudioData(SdfLayerHandle layer) const; 90 | RenderStudioDataPtr _GetRenderStudioData(const SdfLayer& layer) const; 91 | 92 | friend class RenderStudioResolver; 93 | mutable RenderStudioLayerRegistry mLayerRegistry; 94 | std::shared_ptr mWebsocketClient; 95 | 96 | // Main logic 97 | std::map> mAccumulatedDeltas; 98 | std::map> mAccumulatedAcknowledges; 99 | std::vector mRequestedReloads; 100 | std::mutex mEventMutex; 101 | bool mReloadInProgress = false; 102 | 103 | // Processing methods 104 | void ProcessDeltaEvent(const RenderStudio::API::DeltaEvent& v); 105 | void ProcessHistoryEvent(const RenderStudio::API::HistoryEvent& v); 106 | void ProcessAcknowledgeEvent(const RenderStudio::API::AcknowledgeEvent& v); 107 | void ProcessReloadEvent(const RenderStudio::API::ReloadEvent& v); 108 | }; 109 | 110 | PXR_NAMESPACE_CLOSE_SCOPE 111 | -------------------------------------------------------------------------------- /Sources/Resolver/Registry.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Registry.h" 16 | 17 | #pragma warning(push, 0) 18 | 19 | #include 20 | 21 | #pragma warning(pop) 22 | 23 | #include 24 | 25 | PXR_NAMESPACE_OPEN_SCOPE 26 | 27 | void 28 | RenderStudioLayerRegistry::AddLayer(SdfLayerHandle layer) 29 | { 30 | mCreatedLayers[layer->GetIdentifier()] = layer; 31 | } 32 | 33 | void 34 | RenderStudioLayerRegistry::RemoveLayer(SdfLayerHandle layer) 35 | { 36 | if (mCreatedLayers.find(layer->GetIdentifier()) == mCreatedLayers.end()) 37 | { 38 | return; 39 | } 40 | 41 | mCreatedLayers.erase(layer->GetIdentifier()); 42 | } 43 | 44 | void 45 | RenderStudioLayerRegistry::RemoveExpiredLayers() 46 | { 47 | std::experimental::erase_if(mCreatedLayers, [](const auto& pair) { return pair.second.IsExpired(); }); 48 | } 49 | void 50 | RenderStudioLayerRegistry::ForEachLayer(const std::function& fn) 51 | { 52 | RemoveExpiredLayers(); 53 | 54 | for (const auto& [identifier, layer] : mCreatedLayers) 55 | { 56 | if (!layer.IsExpired()) 57 | { 58 | fn(layer); 59 | } 60 | } 61 | } 62 | 63 | SdfLayerHandle 64 | RenderStudioLayerRegistry::GetByIdentifier(const std::string& identifier) 65 | { 66 | if (mCreatedLayers.count(identifier)) 67 | { 68 | return mCreatedLayers[identifier]; 69 | } 70 | else 71 | { 72 | return {}; 73 | } 74 | } 75 | 76 | PXR_NAMESPACE_CLOSE_SCOPE 77 | -------------------------------------------------------------------------------- /Sources/Resolver/Registry.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | #pragma warning(pop) 20 | 21 | PXR_NAMESPACE_OPEN_SCOPE 22 | 23 | class RenderStudioLayerRegistry 24 | { 25 | public: 26 | void AddLayer(SdfLayerHandle layer); 27 | void RemoveLayer(SdfLayerHandle layer); 28 | void RemoveExpiredLayers(); 29 | void ForEachLayer(const std::function& fn); 30 | SdfLayerHandle GetByIdentifier(const std::string& identifier); 31 | 32 | private: 33 | std::map mCreatedLayers; 34 | }; 35 | 36 | PXR_NAMESPACE_CLOSE_SCOPE 37 | -------------------------------------------------------------------------------- /Sources/Resolver/Resolver.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #pragma warning(pop) 25 | 26 | #include "FileFormat.h" 27 | 28 | namespace RenderStudio::Kit 29 | { 30 | struct LiveSessionInfo; 31 | } 32 | 33 | PXR_NAMESPACE_OPEN_SCOPE 34 | 35 | class RenderStudioResolver : public ArDefaultResolver 36 | { 37 | public: 38 | AR_API 39 | RenderStudioResolver(); 40 | 41 | AR_API 42 | virtual ~RenderStudioResolver(); 43 | 44 | AR_API 45 | static void StartLiveMode(const RenderStudio::Kit::LiveSessionInfo& info); 46 | 47 | AR_API 48 | static bool ProcessLiveUpdates(); 49 | 50 | AR_API 51 | static void StopLiveMode(); 52 | 53 | AR_API 54 | static std::string GetLocalStorageUrl(); 55 | 56 | AR_API 57 | static std::string GetCurrentUserId(); 58 | 59 | AR_API 60 | static bool IsRenderStudioPath(const std::string& path); 61 | 62 | AR_API 63 | static bool IsUnresolvable(const std::string& path); 64 | 65 | AR_API 66 | static void SetWorkspacePath(const std::string& path); 67 | 68 | AR_API 69 | static std::string GetWorkspacePath(); 70 | 71 | AR_API 72 | static std::string Unresolve(const std::string& path); 73 | 74 | AR_API 75 | virtual std::string _GetExtension(const std::string& path) const override; 76 | 77 | AR_API 78 | virtual ArResolvedPath _Resolve(const std::string& path) const override; 79 | 80 | AR_API 81 | static std::string ResolveImpl(const std::string& path); 82 | 83 | protected: 84 | AR_API 85 | std::string _CreateIdentifier(const std::string& assetPath, const ArResolvedPath& anchorAssetPath) const override; 86 | 87 | AR_API 88 | virtual std::shared_ptr _OpenAsset(const ArResolvedPath& resolvedPath) const override; 89 | 90 | private: 91 | static std::filesystem::path GetRootPath(); 92 | static std::filesystem::path GetAssetsCachePath(); 93 | 94 | static std::unique_ptr sLiveModeInfo; 95 | static inline RenderStudioFileFormatPtr sFileFormat; 96 | static inline std::filesystem::path sWorkspacePath; 97 | }; 98 | 99 | PXR_NAMESPACE_CLOSE_SCOPE 100 | -------------------------------------------------------------------------------- /Sources/Resolver/plugInfo.json: -------------------------------------------------------------------------------- 1 | # Portions of this file auto-generated by usdGenSchema. 2 | # Edits will survive regeneration except for comments and 3 | # changes to types with autoGenerated=true. 4 | { 5 | "Plugins": [ 6 | { 7 | "Info": { 8 | "Types": { 9 | "RenderStudioFileFormat": { 10 | "bases": [ 11 | "SdfFileFormat" 12 | ], 13 | "displayName": "AMD RenderStudio file format", 14 | "extensions": [ 15 | "studio" 16 | ], 17 | "formatId": "studio", 18 | "primary": true, 19 | "target": "usd" 20 | }, 21 | "RenderStudioResolver": { 22 | "bases": [ 23 | "ArResolver" 24 | ], 25 | "primary": true, 26 | "uriSchemes": [ 27 | "studio", 28 | "gpuopen", 29 | "storage" 30 | ] 31 | } 32 | } 33 | }, 34 | "LibraryPath": "../@PLUGIN_LIBRARY_NAME@", 35 | "Name": "RenderStudioResolver", 36 | "ResourcePath": "resources", 37 | "Root": "..", 38 | "Type": "library" 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Schema/AiTools.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include 21 | 22 | namespace RenderStudio::AI 23 | { 24 | 25 | struct AssistantPrimitiveInfo 26 | { 27 | std::string name; 28 | pxr::GfVec2f position; 29 | float rotation; 30 | std::string file; 31 | }; 32 | 33 | AssistantPrimitiveInfo tag_invoke(boost::json::value_to_tag, boost::json::value const& json); 34 | 35 | struct AssistantResponse 36 | { 37 | std::string description; 38 | std::vector furniture; 39 | }; 40 | 41 | AssistantResponse tag_invoke(boost::json::value_to_tag, boost::json::value const& json); 42 | 43 | class Tools 44 | { 45 | public: 46 | static std::optional ProcessPrompt(const std::string& prompt, const pxr::UsdPrim& root); 47 | }; 48 | 49 | } // namespace RenderStudio::AI 50 | -------------------------------------------------------------------------------- /Sources/Schema/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | set(KIT_TARGET_NAME "RenderStudioSchema") 17 | 18 | # Create target 19 | file(GLOB SOURCES *.h *.cpp) 20 | add_library(${KIT_TARGET_NAME} SHARED ${SOURCES}) 21 | 22 | # Link libraries 23 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 24 | Boost::boost 25 | usdGeom 26 | usd 27 | RenderStudioLogger 28 | RenderStudioNetworking 29 | ) 30 | 31 | if (TBB_INCLUDE_DIR) 32 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE ${TBB_LIBRARY}) 33 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ${TBB_INCLUDE_DIR}) 34 | endif() 35 | 36 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ..) 37 | 38 | if(MAYA_SUPPORT) 39 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 40 | ${PYTHON_LIBRARIES} 41 | ) 42 | else() 43 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 44 | Boost::python 45 | ) 46 | endif() 47 | 48 | # Set compile options 49 | target_compile_definitions(${KIT_TARGET_NAME} PRIVATE 50 | RENDERSTUDIOSCHEMA_EXPORTS 51 | ) 52 | 53 | # Install library 54 | install(TARGETS ${KIT_TARGET_NAME} 55 | DESTINATION plugin/usd) 56 | 57 | # Install plugInfo 58 | if(WIN32) 59 | set(PLUGIN_LIBRARY_NAME RenderStudioSchema.dll) 60 | elseif(UNIX) 61 | set(PLUGIN_LIBRARY_NAME libRenderStudioSchema.so) 62 | endif() 63 | 64 | configure_file(plugInfo.json plugInfo.json @ONLY) 65 | 66 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/plugInfo.json 67 | DESTINATION plugin/usd/RenderStudioSchema/resources) 68 | 69 | # Install headers 70 | file(GLOB HEADERS *.h) 71 | install(FILES ${HEADERS} DESTINATION include/RenderStudio/Schema) 72 | 73 | SetDefaultCompileDefinitions(${KIT_TARGET_NAME}) 74 | 75 | # Install library 76 | install(TARGETS ${KIT_TARGET_NAME} DESTINATION plugin/usd) 77 | -------------------------------------------------------------------------------- /Sources/Schema/api.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Pixar 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 | // with the following modification; you may not use this file except in 6 | // compliance with the Apache License and the following modification to it: 7 | // Section 6. Trademarks. is deleted and replaced with: 8 | // 9 | // 6. Trademarks. This License does not grant permission to use the trade 10 | // names, trademarks, service marks, or product names of the Licensor 11 | // and its affiliates, except as required to comply with Section 4(c) of 12 | // the License and to reproduce the content of the NOTICE file. 13 | // 14 | // You may obtain a copy of the Apache License at 15 | // 16 | // http://www.apache.org/licenses/LICENSE-2.0 17 | // 18 | // Unless required by applicable law or agreed to in writing, software 19 | // distributed under the Apache License with the above modification is 20 | // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 | // KIND, either express or implied. See the Apache License for the specific 22 | // language governing permissions and limitations under the Apache License. 23 | // 24 | #ifndef RENDERSTUDIOSCHEMA_API_H 25 | #define RENDERSTUDIOSCHEMA_API_H 26 | 27 | #include "pxr/base/arch/export.h" 28 | 29 | #if defined(PXR_STATIC) 30 | #define RENDERSTUDIOSCHEMA_API 31 | #define RENDERSTUDIOSCHEMA_API_TEMPLATE_CLASS(...) 32 | #define RENDERSTUDIOSCHEMA_API_TEMPLATE_STRUCT(...) 33 | #define RENDERSTUDIOSCHEMA_LOCAL 34 | #else 35 | #if defined(RENDERSTUDIOSCHEMA_EXPORTS) 36 | #define RENDERSTUDIOSCHEMA_API ARCH_EXPORT 37 | #define RENDERSTUDIOSCHEMA_API_TEMPLATE_CLASS(...) ARCH_EXPORT_TEMPLATE(class, __VA_ARGS__) 38 | #define RENDERSTUDIOSCHEMA_API_TEMPLATE_STRUCT(...) ARCH_EXPORT_TEMPLATE(struct, __VA_ARGS__) 39 | #else 40 | #define RENDERSTUDIOSCHEMA_API ARCH_IMPORT 41 | #define RENDERSTUDIOSCHEMA_API_TEMPLATE_CLASS(...) ARCH_IMPORT_TEMPLATE(class, __VA_ARGS__) 42 | #define RENDERSTUDIOSCHEMA_API_TEMPLATE_STRUCT(...) ARCH_IMPORT_TEMPLATE(struct, __VA_ARGS__) 43 | #endif 44 | #define RENDERSTUDIOSCHEMA_LOCAL ARCH_HIDDEN 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Sources/Schema/generatedSchema.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | "WARNING: THIS FILE IS GENERATED BY usdGenSchema. DO NOT EDIT." 4 | ) 5 | 6 | class "RenderStudioAiPrimAPI" 7 | { 8 | string generated:description ( 9 | doc = "String value denoting generated description" 10 | ) 11 | string params:prompt ( 12 | doc = "String value denoting prompt" 13 | ) 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Sources/Schema/plugInfo.json: -------------------------------------------------------------------------------- 1 | # Portions of this file auto-generated by usdGenSchema. 2 | # Edits will survive regeneration except for comments and 3 | # changes to types with autoGenerated=true. 4 | { 5 | "Plugins": [ 6 | { 7 | "Info": { 8 | "Types": { 9 | "RenderStudioAiPrimAPI": { 10 | "autoGenerated": true, 11 | "bases": [ 12 | "UsdAPISchemaBase" 13 | ], 14 | "schemaKind": "singleApplyAPI" 15 | } 16 | } 17 | }, 18 | "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", 19 | "Name": "RenderStudioSchema", 20 | "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", 21 | "Root": "..", 22 | "Type": "library" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Schema/renderStudioAiPrimAPI.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Pixar 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 | // with the following modification; you may not use this file except in 6 | // compliance with the Apache License and the following modification to it: 7 | // Section 6. Trademarks. is deleted and replaced with: 8 | // 9 | // 6. Trademarks. This License does not grant permission to use the trade 10 | // names, trademarks, service marks, or product names of the Licensor 11 | // and its affiliates, except as required to comply with Section 4(c) of 12 | // the License and to reproduce the content of the NOTICE file. 13 | // 14 | // You may obtain a copy of the Apache License at 15 | // 16 | // http://www.apache.org/licenses/LICENSE-2.0 17 | // 18 | // Unless required by applicable law or agreed to in writing, software 19 | // distributed under the Apache License with the above modification is 20 | // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 | // KIND, either express or implied. See the Apache License for the specific 22 | // language governing permissions and limitations under the Apache License. 23 | // 24 | #include "./renderStudioAiPrimAPI.h" 25 | 26 | #include "pxr/usd/sdf/assetPath.h" 27 | #include "pxr/usd/sdf/types.h" 28 | #include "pxr/usd/usd/schemaRegistry.h" 29 | #include "pxr/usd/usd/tokens.h" 30 | #include "pxr/usd/usd/typed.h" 31 | 32 | PXR_NAMESPACE_OPEN_SCOPE 33 | 34 | // Register the schema with the TfType system. 35 | TF_REGISTRY_FUNCTION(TfType) { TfType::Define>(); } 36 | 37 | TF_DEFINE_PRIVATE_TOKENS(_schemaTokens, (RenderStudioAiPrimAPI)); 38 | 39 | /* virtual */ 40 | RenderStudioAiPrimAPI::~RenderStudioAiPrimAPI() { } 41 | 42 | /* static */ 43 | RenderStudioAiPrimAPI 44 | RenderStudioAiPrimAPI::Get(const UsdStagePtr& stage, const SdfPath& path) 45 | { 46 | if (!stage) 47 | { 48 | TF_CODING_ERROR("Invalid stage"); 49 | return RenderStudioAiPrimAPI(); 50 | } 51 | return RenderStudioAiPrimAPI(stage->GetPrimAtPath(path)); 52 | } 53 | 54 | /* virtual */ 55 | UsdSchemaKind 56 | RenderStudioAiPrimAPI::_GetSchemaKind() const 57 | { 58 | return RenderStudioAiPrimAPI::schemaKind; 59 | } 60 | 61 | /* static */ 62 | bool 63 | RenderStudioAiPrimAPI::CanApply(const UsdPrim& prim, std::string* whyNot) 64 | { 65 | return prim.CanApplyAPI(whyNot); 66 | } 67 | 68 | /* static */ 69 | RenderStudioAiPrimAPI 70 | RenderStudioAiPrimAPI::Apply(const UsdPrim& prim) 71 | { 72 | if (prim.ApplyAPI()) 73 | { 74 | return RenderStudioAiPrimAPI(prim); 75 | } 76 | return RenderStudioAiPrimAPI(); 77 | } 78 | 79 | /* static */ 80 | const TfType& 81 | RenderStudioAiPrimAPI::_GetStaticTfType() 82 | { 83 | static TfType tfType = TfType::Find(); 84 | return tfType; 85 | } 86 | 87 | /* static */ 88 | bool 89 | RenderStudioAiPrimAPI::_IsTypedSchema() 90 | { 91 | static bool isTyped = _GetStaticTfType().IsA(); 92 | return isTyped; 93 | } 94 | 95 | /* virtual */ 96 | const TfType& 97 | RenderStudioAiPrimAPI::_GetTfType() const 98 | { 99 | return _GetStaticTfType(); 100 | } 101 | 102 | UsdAttribute 103 | RenderStudioAiPrimAPI::GetPromptAttr() const 104 | { 105 | return GetPrim().GetAttribute(Tokens->paramsPrompt); 106 | } 107 | 108 | UsdAttribute 109 | RenderStudioAiPrimAPI::CreatePromptAttr(VtValue const& defaultValue, bool writeSparsely) const 110 | { 111 | return UsdSchemaBase::_CreateAttr( 112 | Tokens->paramsPrompt, 113 | SdfValueTypeNames->String, 114 | /* custom = */ false, 115 | SdfVariabilityVarying, 116 | defaultValue, 117 | writeSparsely); 118 | } 119 | 120 | UsdAttribute 121 | RenderStudioAiPrimAPI::GetDescriptionAttr() const 122 | { 123 | return GetPrim().GetAttribute(Tokens->generatedDescription); 124 | } 125 | 126 | UsdAttribute 127 | RenderStudioAiPrimAPI::CreateDescriptionAttr(VtValue const& defaultValue, bool writeSparsely) const 128 | { 129 | return UsdSchemaBase::_CreateAttr( 130 | Tokens->generatedDescription, 131 | SdfValueTypeNames->String, 132 | /* custom = */ false, 133 | SdfVariabilityVarying, 134 | defaultValue, 135 | writeSparsely); 136 | } 137 | 138 | namespace 139 | { 140 | static inline TfTokenVector 141 | _ConcatenateAttributeNames(const TfTokenVector& left, const TfTokenVector& right) 142 | { 143 | TfTokenVector result; 144 | result.reserve(left.size() + right.size()); 145 | result.insert(result.end(), left.begin(), left.end()); 146 | result.insert(result.end(), right.begin(), right.end()); 147 | return result; 148 | } 149 | } // namespace 150 | 151 | /*static*/ 152 | const TfTokenVector& 153 | RenderStudioAiPrimAPI::GetSchemaAttributeNames(bool includeInherited) 154 | { 155 | static TfTokenVector localNames = { 156 | Tokens->paramsPrompt, 157 | Tokens->generatedDescription, 158 | }; 159 | static TfTokenVector allNames 160 | = _ConcatenateAttributeNames(UsdAPISchemaBase::GetSchemaAttributeNames(true), localNames); 161 | 162 | if (includeInherited) 163 | return allNames; 164 | else 165 | return localNames; 166 | } 167 | 168 | PXR_NAMESPACE_CLOSE_SCOPE 169 | 170 | // ===================================================================== // 171 | // Feel free to add custom code below this line. It will be preserved by 172 | // the code generator. 173 | // 174 | // Just remember to wrap code in the appropriate delimiters: 175 | // 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'. 176 | // ===================================================================== // 177 | // --(BEGIN CUSTOM CODE)-- 178 | 179 | #include 180 | 181 | #include "AiTools.h" 182 | 183 | #include 184 | 185 | PXR_NAMESPACE_OPEN_SCOPE 186 | 187 | void 188 | RenderStudioAiPrimAPI::Generate() 189 | { 190 | // Guard has attribute 191 | if (!GetPromptAttr().HasAuthoredValue()) 192 | { 193 | LOG_WARNING << "RenderStudioAiPrimAPI::Generate() called without authored prompt"; 194 | return; 195 | } 196 | 197 | std::string prompt; 198 | GetPromptAttr().Get(&prompt); 199 | 200 | // Guard has attribute value 201 | if (prompt.empty()) 202 | { 203 | LOG_WARNING << "RenderStudioAiPrimAPI::Generate() called with empty prompt"; 204 | return; 205 | } 206 | 207 | // Clear previous generation 208 | for (const auto& prim : GetPrim().GetChildren()) 209 | { 210 | GetPrim().GetStage()->RemovePrim(prim.GetPath()); 211 | } 212 | 213 | GetDescriptionAttr().Clear(); 214 | 215 | // Do new generation 216 | auto description = RenderStudio::AI::Tools::ProcessPrompt(prompt, GetPrim()); 217 | 218 | if (description.has_value()) 219 | { 220 | CreateDescriptionAttr().Set(description.value()); 221 | } 222 | } 223 | 224 | PXR_NAMESPACE_CLOSE_SCOPE 225 | -------------------------------------------------------------------------------- /Sources/Schema/schema.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | """ This file describes RenderStudio primitives schema for AI/ML driven operations. 4 | """ 5 | subLayers = [ 6 | @usd/schema.usda@ 7 | ] 8 | ) 9 | 10 | over "GLOBAL" ( 11 | customData = { 12 | string libraryName = "RenderStudioSchema" 13 | string libraryPath = "." 14 | string libraryPrefix = "" 15 | } 16 | ) { 17 | } 18 | 19 | class "RenderStudioAiPrimAPI" ( 20 | inherits = 21 | customData = { 22 | token apiSchemaType = "singleApply" 23 | } 24 | ) 25 | { 26 | string params:prompt ( 27 | customData = { 28 | string apiName = "prompt" 29 | } 30 | doc = "String value denoting prompt" 31 | ) 32 | 33 | string generated:description ( 34 | customData = { 35 | string apiName = "description" 36 | } 37 | doc = "String value denoting generated description" 38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Schema/tokens.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Pixar 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 | // with the following modification; you may not use this file except in 6 | // compliance with the Apache License and the following modification to it: 7 | // Section 6. Trademarks. is deleted and replaced with: 8 | // 9 | // 6. Trademarks. This License does not grant permission to use the trade 10 | // names, trademarks, service marks, or product names of the Licensor 11 | // and its affiliates, except as required to comply with Section 4(c) of 12 | // the License and to reproduce the content of the NOTICE file. 13 | // 14 | // You may obtain a copy of the Apache License at 15 | // 16 | // http://www.apache.org/licenses/LICENSE-2.0 17 | // 18 | // Unless required by applicable law or agreed to in writing, software 19 | // distributed under the Apache License with the above modification is 20 | // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 | // KIND, either express or implied. See the Apache License for the specific 22 | // language governing permissions and limitations under the Apache License. 23 | // 24 | #include "./tokens.h" 25 | 26 | PXR_NAMESPACE_OPEN_SCOPE 27 | 28 | TokensType::TokensType() 29 | : generatedDescription("generated:description", TfToken::Immortal) 30 | , paramsPrompt("params:prompt", TfToken::Immortal) 31 | , allTokens({ generatedDescription, paramsPrompt }) 32 | { 33 | } 34 | 35 | TfStaticData Tokens; 36 | 37 | PXR_NAMESPACE_CLOSE_SCOPE 38 | -------------------------------------------------------------------------------- /Sources/Schema/tokens.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Pixar 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 | // with the following modification; you may not use this file except in 6 | // compliance with the Apache License and the following modification to it: 7 | // Section 6. Trademarks. is deleted and replaced with: 8 | // 9 | // 6. Trademarks. This License does not grant permission to use the trade 10 | // names, trademarks, service marks, or product names of the Licensor 11 | // and its affiliates, except as required to comply with Section 4(c) of 12 | // the License and to reproduce the content of the NOTICE file. 13 | // 14 | // You may obtain a copy of the Apache License at 15 | // 16 | // http://www.apache.org/licenses/LICENSE-2.0 17 | // 18 | // Unless required by applicable law or agreed to in writing, software 19 | // distributed under the Apache License with the above modification is 20 | // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 | // KIND, either express or implied. See the Apache License for the specific 22 | // language governing permissions and limitations under the Apache License. 23 | // 24 | #ifndef _TOKENS_H 25 | #define _TOKENS_H 26 | 27 | /// \file RenderStudioSchema/tokens.h 28 | 29 | // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 30 | // 31 | // This is an automatically generated file (by usdGenSchema.py). 32 | // Do not hand-edit! 33 | // 34 | // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 35 | 36 | #include 37 | 38 | #include "./api.h" 39 | #include "pxr/base/tf/staticData.h" 40 | #include "pxr/base/tf/token.h" 41 | #include "pxr/pxr.h" 42 | 43 | PXR_NAMESPACE_OPEN_SCOPE 44 | 45 | /// \class TokensType 46 | /// 47 | /// \link Tokens \endlink provides static, efficient 48 | /// \link TfToken TfTokens\endlink for use in all public USD API. 49 | /// 50 | /// These tokens are auto-generated from the module's schema, representing 51 | /// property names, for when you need to fetch an attribute or relationship 52 | /// directly by name, e.g. UsdPrim::GetAttribute(), in the most efficient 53 | /// manner, and allow the compiler to verify that you spelled the name 54 | /// correctly. 55 | /// 56 | /// Tokens also contains all of the \em allowedTokens values 57 | /// declared for schema builtin attributes of 'token' scene description type. 58 | /// Use Tokens like so: 59 | /// 60 | /// \code 61 | /// gprim.GetMyTokenValuedAttr().Set(Tokens->generatedDescription); 62 | /// \endcode 63 | struct TokensType 64 | { 65 | RENDERSTUDIOSCHEMA_API TokensType(); 66 | /// \brief "generated:description" 67 | /// 68 | /// RenderStudioAiPrimAPI 69 | const TfToken generatedDescription; 70 | /// \brief "params:prompt" 71 | /// 72 | /// RenderStudioAiPrimAPI 73 | const TfToken paramsPrompt; 74 | /// A vector of all of the tokens listed above. 75 | const std::vector allTokens; 76 | }; 77 | 78 | /// \var Tokens 79 | /// 80 | /// A global variable with static, efficient \link TfToken TfTokens\endlink 81 | /// for use in all public USD API. \sa TokensType 82 | extern RENDERSTUDIOSCHEMA_API TfStaticData Tokens; 83 | 84 | PXR_NAMESPACE_CLOSE_SCOPE 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /Sources/Schema/wrapRenderStudioAiPrimAPI.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Pixar 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 | // with the following modification; you may not use this file except in 6 | // compliance with the Apache License and the following modification to it: 7 | // Section 6. Trademarks. is deleted and replaced with: 8 | // 9 | // 6. Trademarks. This License does not grant permission to use the trade 10 | // names, trademarks, service marks, or product names of the Licensor 11 | // and its affiliates, except as required to comply with Section 4(c) of 12 | // the License and to reproduce the content of the NOTICE file. 13 | // 14 | // You may obtain a copy of the Apache License at 15 | // 16 | // http://www.apache.org/licenses/LICENSE-2.0 17 | // 18 | // Unless required by applicable law or agreed to in writing, software 19 | // distributed under the Apache License with the above modification is 20 | // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 | // KIND, either express or implied. See the Apache License for the specific 22 | // language governing permissions and limitations under the Apache License. 23 | // 24 | #include 25 | 26 | #include "./renderStudioAiPrimAPI.h" 27 | #include "pxr/base/tf/pyAnnotatedBoolResult.h" 28 | #include "pxr/base/tf/pyContainerConversions.h" 29 | #include "pxr/base/tf/pyResultConversions.h" 30 | #include "pxr/base/tf/pyUtils.h" 31 | #include "pxr/base/tf/wrapTypeHelpers.h" 32 | #include "pxr/usd/sdf/primSpec.h" 33 | #include "pxr/usd/usd/pyConversions.h" 34 | #include "pxr/usd/usd/schemaBase.h" 35 | 36 | #include 37 | 38 | using namespace boost::python; 39 | 40 | PXR_NAMESPACE_USING_DIRECTIVE 41 | 42 | namespace 43 | { 44 | 45 | #define WRAP_CUSTOM template static void _CustomWrapCode(Cls& _class) 46 | 47 | // fwd decl. 48 | WRAP_CUSTOM; 49 | 50 | static UsdAttribute 51 | _CreatePromptAttr(RenderStudioAiPrimAPI& self, object defaultVal, bool writeSparsely) 52 | { 53 | return self.CreatePromptAttr(UsdPythonToSdfType(defaultVal, SdfValueTypeNames->String), writeSparsely); 54 | } 55 | 56 | static UsdAttribute 57 | _CreateDescriptionAttr(RenderStudioAiPrimAPI& self, object defaultVal, bool writeSparsely) 58 | { 59 | return self.CreateDescriptionAttr(UsdPythonToSdfType(defaultVal, SdfValueTypeNames->String), writeSparsely); 60 | } 61 | 62 | static std::string 63 | _Repr(const RenderStudioAiPrimAPI& self) 64 | { 65 | std::string primRepr = TfPyRepr(self.GetPrim()); 66 | return TfStringPrintf("RenderStudioSchema.RenderStudioAiPrimAPI(%s)", primRepr.c_str()); 67 | } 68 | 69 | struct RenderStudioAiPrimAPI_CanApplyResult : public TfPyAnnotatedBoolResult 70 | { 71 | RenderStudioAiPrimAPI_CanApplyResult(bool val, std::string const& msg) 72 | : TfPyAnnotatedBoolResult(val, msg) 73 | { 74 | } 75 | }; 76 | 77 | static RenderStudioAiPrimAPI_CanApplyResult 78 | _WrapCanApply(const UsdPrim& prim) 79 | { 80 | std::string whyNot; 81 | bool result = RenderStudioAiPrimAPI::CanApply(prim, &whyNot); 82 | return RenderStudioAiPrimAPI_CanApplyResult(result, whyNot); 83 | } 84 | 85 | } // anonymous namespace 86 | 87 | void 88 | wrapRenderStudioAiPrimAPI() 89 | { 90 | typedef RenderStudioAiPrimAPI This; 91 | 92 | RenderStudioAiPrimAPI_CanApplyResult::Wrap("_CanApplyResult", "whyNot"); 93 | 94 | class_> cls("RenderStudioAiPrimAPI"); 95 | 96 | cls.def(init(arg("prim"))) 97 | .def(init(arg("schemaObj"))) 98 | .def(TfTypePythonClass()) 99 | 100 | .def("Get", &This::Get, (arg("stage"), arg("path"))) 101 | .staticmethod("Get") 102 | 103 | .def("CanApply", &_WrapCanApply, (arg("prim"))) 104 | .staticmethod("CanApply") 105 | 106 | .def("Apply", &This::Apply, (arg("prim"))) 107 | .staticmethod("Apply") 108 | 109 | .def( 110 | "GetSchemaAttributeNames", 111 | &This::GetSchemaAttributeNames, 112 | arg("includeInherited") = true, 113 | return_value_policy()) 114 | .staticmethod("GetSchemaAttributeNames") 115 | 116 | .def("_GetStaticTfType", (TfType const& (*)())TfType::Find, return_value_policy()) 117 | .staticmethod("_GetStaticTfType") 118 | 119 | .def(!self) 120 | 121 | .def("GetPromptAttr", &This::GetPromptAttr) 122 | .def("CreatePromptAttr", &_CreatePromptAttr, (arg("defaultValue") = object(), arg("writeSparsely") = false)) 123 | 124 | .def("GetDescriptionAttr", &This::GetDescriptionAttr) 125 | .def( 126 | "CreateDescriptionAttr", 127 | &_CreateDescriptionAttr, 128 | (arg("defaultValue") = object(), arg("writeSparsely") = false)) 129 | 130 | .def("__repr__", ::_Repr); 131 | 132 | _CustomWrapCode(cls); 133 | } 134 | 135 | // ===================================================================== // 136 | // Feel free to add custom code below this line, it will be preserved by 137 | // the code generator. The entry point for your custom code should look 138 | // minimally like the following: 139 | // 140 | // WRAP_CUSTOM { 141 | // _class 142 | // .def("MyCustomMethod", ...) 143 | // ; 144 | // } 145 | // 146 | // Of course any other ancillary or support code may be provided. 147 | // 148 | // Just remember to wrap code in the appropriate delimiters: 149 | // 'namespace {', '}'. 150 | // 151 | // ===================================================================== // 152 | // --(BEGIN CUSTOM CODE)-- 153 | 154 | namespace 155 | { 156 | 157 | WRAP_CUSTOM { } 158 | 159 | } // namespace 160 | -------------------------------------------------------------------------------- /Sources/Schema/wrapTokens.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Pixar 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 | // with the following modification; you may not use this file except in 6 | // compliance with the Apache License and the following modification to it: 7 | // Section 6. Trademarks. is deleted and replaced with: 8 | // 9 | // 6. Trademarks. This License does not grant permission to use the trade 10 | // names, trademarks, service marks, or product names of the Licensor 11 | // and its affiliates, except as required to comply with Section 4(c) of 12 | // the License and to reproduce the content of the NOTICE file. 13 | // 14 | // You may obtain a copy of the Apache License at 15 | // 16 | // http://www.apache.org/licenses/LICENSE-2.0 17 | // 18 | // Unless required by applicable law or agreed to in writing, software 19 | // distributed under the Apache License with the above modification is 20 | // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 | // KIND, either express or implied. See the Apache License for the specific 22 | // language governing permissions and limitations under the Apache License. 23 | // 24 | // GENERATED FILE. DO NOT EDIT. 25 | #include "./tokens.h" 26 | 27 | #include 28 | 29 | PXR_NAMESPACE_USING_DIRECTIVE 30 | 31 | namespace 32 | { 33 | 34 | // Helper to return a static token as a string. We wrap tokens as Python 35 | // strings and for some reason simply wrapping the token using def_readonly 36 | // bypasses to-Python conversion, leading to the error that there's no 37 | // Python type for the C++ TfToken type. So we wrap this functor instead. 38 | class _WrapStaticToken 39 | { 40 | public: 41 | _WrapStaticToken(const TfToken* token) 42 | : _token(token) 43 | { 44 | } 45 | 46 | std::string operator()() const { return _token->GetString(); } 47 | 48 | private: 49 | const TfToken* _token; 50 | }; 51 | 52 | template 53 | void 54 | _AddToken(T& cls, const char* name, const TfToken& token) 55 | { 56 | cls.add_static_property( 57 | name, 58 | boost::python::make_function( 59 | _WrapStaticToken(&token), 60 | boost::python::return_value_policy(), 61 | boost::mpl::vector1())); 62 | } 63 | 64 | } // namespace 65 | 66 | void 67 | wrapTokens() 68 | { 69 | boost::python::class_ cls("Tokens", boost::python::no_init); 70 | _AddToken(cls, "generatedDescription", Tokens->generatedDescription); 71 | _AddToken(cls, "paramsPrompt", Tokens->paramsPrompt); 72 | } 73 | -------------------------------------------------------------------------------- /Sources/Serialization/Api.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #pragma warning(push, 0) 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #pragma warning(pop) 33 | 34 | namespace RenderStudio::API 35 | { 36 | 37 | PXR_NAMESPACE_USING_DIRECTIVE 38 | using namespace boost::json; 39 | 40 | struct SpecData 41 | { 42 | SdfSpecType specType = SdfSpecTypeUnknown; 43 | std::vector> fields; 44 | }; 45 | 46 | void tag_invoke(const value_from_tag&, value& json, const SpecData& v); 47 | SpecData tag_invoke(const value_to_tag&, const value& json); 48 | 49 | struct DeltaEvent 50 | { 51 | std::string layer; 52 | std::string user; 53 | std::optional sequence; 54 | TfHashMap updates; 55 | }; 56 | 57 | void tag_invoke(const value_from_tag&, value& json, const DeltaEvent& v); 58 | DeltaEvent tag_invoke(const value_to_tag&, const value& json); 59 | 60 | struct AcknowledgeEvent 61 | { 62 | std::string layer; 63 | std::vector paths; 64 | std::size_t sequence = 0; 65 | }; 66 | 67 | void tag_invoke(const value_from_tag&, value& json, const AcknowledgeEvent& v); 68 | AcknowledgeEvent tag_invoke(const value_to_tag&, const value& json); 69 | 70 | struct HistoryEvent 71 | { 72 | }; 73 | 74 | void tag_invoke(const value_from_tag&, value& json, const HistoryEvent& v); 75 | HistoryEvent tag_invoke(const value_to_tag&, const value& json); 76 | 77 | struct ReloadEvent 78 | { 79 | std::string layer; 80 | std::string user; 81 | std::optional sequence; 82 | }; 83 | 84 | void tag_invoke(const value_from_tag&, value& json, const ReloadEvent& v); 85 | ReloadEvent tag_invoke(const value_to_tag&, const value& json); 86 | 87 | struct Event 88 | { 89 | std::string event; 90 | std::variant body; 91 | }; 92 | 93 | void tag_invoke(const value_from_tag&, value& json, const Event& v); 94 | Event tag_invoke(const value_to_tag&, const value& json); 95 | 96 | } // namespace RenderStudio::API 97 | -------------------------------------------------------------------------------- /Sources/Serialization/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | set(KIT_TARGET_NAME "RenderStudioSerialization") 17 | 18 | set(CMAKE_CXX_STANDARD 20) 19 | 20 | # Create target 21 | file(GLOB SOURCES *.h *.cpp) 22 | add_library(${KIT_TARGET_NAME} STATIC ${SOURCES}) 23 | 24 | # Link libraries 25 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 26 | Boost::boost 27 | Boost::python 28 | sdf 29 | ) 30 | 31 | if (TBB_INCLUDE_DIR) 32 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ${TBB_INCLUDE_DIR}) 33 | endif() 34 | 35 | # Install headers 36 | install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Serialization.h ${CMAKE_CURRENT_SOURCE_DIR}/Api.h 37 | DESTINATION include/RenderStudio/Serialization) 38 | 39 | SetDefaultCompileDefinitions(${KIT_TARGET_NAME}) 40 | SetMaxWarningLevel(${KIT_TARGET_NAME}) 41 | SetDefaultCompileDefinitions(${KIT_TARGET_NAME}) 42 | -------------------------------------------------------------------------------- /Sources/Server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | project(RenderStudioServer) 17 | 18 | set(CMAKE_CXX_STANDARD 20) 19 | 20 | # Create target 21 | file(GLOB SOURCES *.h *.cpp) 22 | add_executable(${PROJECT_NAME} ${SOURCES}) 23 | 24 | # Link libraries 25 | target_link_libraries(${PROJECT_NAME} PRIVATE 26 | Boost::boost 27 | Boost::python 28 | RenderStudioNetworking 29 | RenderStudioLogger 30 | RenderStudioSerialization 31 | RenderStudioKit 32 | tf 33 | ) 34 | 35 | if (TBB_INCLUDE_DIR) 36 | target_link_libraries(${PROJECT_NAME} PRIVATE ${TBB_LIBRARY}) 37 | target_include_directories(${PROJECT_NAME} PRIVATE ${TBB_INCLUDE_DIR}) 38 | endif() 39 | 40 | if (MAYA_SUPPORT) 41 | target_link_libraries(${PROJECT_NAME} PRIVATE 42 | ${PYTHON_LIBRARIES} 43 | ) 44 | endif() 45 | 46 | target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../) 47 | 48 | SetMaxWarningLevel(${PROJECT_NAME}) 49 | SetDefaultCompileDefinitions(${PROJECT_NAME}) 50 | 51 | # Install headers 52 | install(TARGETS ${PROJECT_NAME} DESTINATION RenderStudioServer) 53 | 54 | if (WIN32) 55 | install(PROGRAMS Run.bat DESTINATION RenderStudioServer) 56 | elseif(UNIX) 57 | install(PROGRAMS Run.sh DESTINATION RenderStudioServer) 58 | endif() 59 | -------------------------------------------------------------------------------- /Sources/Server/Channel.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Channel.h" 16 | 17 | Channel::Channel(const std::string& name) 18 | : mName(name) 19 | { 20 | LOG_INFO << "Created channel \'" << mName << "\'"; 21 | } 22 | 23 | Channel::~Channel() { LOG_INFO << "Removed channel \'" << mName << "\'"; } 24 | 25 | void 26 | Channel::AddConnection(ConnectionPtr connection) 27 | { 28 | mConnections.push_back(connection); 29 | } 30 | 31 | void 32 | Channel::RemoveConnection(ConnectionPtr connection) 33 | { 34 | mConnections.remove_if([&connection](const ConnectionPtr& entry) 35 | { return entry->GetDebugName() == connection->GetDebugName(); }); 36 | } 37 | 38 | void 39 | Channel::Send(ConnectionPtr connection, const std::string& message) 40 | { 41 | for (ConnectionPtr& entry : mConnections) 42 | { 43 | // Skip sender 44 | if (entry->GetDebugName() == connection->GetDebugName()) 45 | { 46 | continue; 47 | } 48 | entry->Send(message); 49 | } 50 | } 51 | 52 | const std::map>& 53 | Channel::GetHistory() const 54 | { 55 | return mHistory; 56 | } 57 | 58 | const std::list& 59 | Channel::GetConnections() const 60 | { 61 | return mConnections; 62 | } 63 | 64 | void 65 | Channel::AddToHistory(const RenderStudio::API::DeltaEvent& v) 66 | { 67 | if (mHistory.find(v.layer) == mHistory.end()) 68 | { 69 | mHistory.insert({ v.layer, {} }); 70 | } 71 | 72 | mHistory.at(v.layer).push_back(v); 73 | } 74 | 75 | void 76 | Channel::ClearHistory(const std::string& layer) 77 | { 78 | if (mHistory.find(layer) == mHistory.end()) 79 | { 80 | return; 81 | } 82 | 83 | mHistory.at(layer).clear(); 84 | } 85 | 86 | bool 87 | Channel::Empty() const 88 | { 89 | return mConnections.empty(); 90 | } 91 | 92 | std::size_t 93 | Channel::GetSequenceNumber(const std::string& layer) const 94 | { 95 | // No history for this layer yet, send first number 96 | if (mHistory.find(layer) == mHistory.end()) 97 | { 98 | return 1; 99 | } 100 | 101 | return mHistory.at(layer).size() + 1; 102 | } 103 | -------------------------------------------------------------------------------- /Sources/Server/Channel.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | using Connection = RenderStudio::Networking::WebsocketSession; 22 | using ConnectionPtr = std::shared_ptr; 23 | 24 | class Channel 25 | { 26 | public: 27 | Channel(const std::string& name); 28 | ~Channel(); 29 | Channel(const Channel& rgs) = delete; 30 | 31 | void AddConnection(ConnectionPtr connection); 32 | void RemoveConnection(ConnectionPtr connection); 33 | void Send(ConnectionPtr connection, const std::string& message); 34 | const std::map>& GetHistory() const; 35 | const std::list& GetConnections() const; 36 | void AddToHistory(const RenderStudio::API::DeltaEvent& v); 37 | void ClearHistory(const std::string& layer); 38 | bool Empty() const; 39 | std::size_t GetSequenceNumber(const std::string& layer) const; 40 | 41 | private: 42 | std::map> mHistory; 43 | std::list mConnections; 44 | std::string mName; 45 | }; 46 | -------------------------------------------------------------------------------- /Sources/Server/Logic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Logic.h" 16 | 17 | template struct Overload : Ts... 18 | { 19 | using Ts::operator()...; 20 | }; 21 | 22 | template Overload(Ts...) -> Overload; 23 | 24 | void 25 | Logic::OnConnected(ConnectionPtr connection) 26 | { 27 | // Thread safety 28 | std::lock_guard lock(mMutex); 29 | 30 | // Get or create channel 31 | auto [iter, inserted] = mChannels.try_emplace(connection->GetChannel(), connection->GetChannel()); 32 | Channel& channel = iter->second; 33 | 34 | // Log 35 | LOG_INFO << "User \'" << connection->GetDebugName() << "\' joined \'" << connection->GetChannel() << "\'"; 36 | channel.AddConnection(connection); 37 | 38 | // Send history 39 | for (const auto& [layer, deltas] : channel.GetHistory()) 40 | { 41 | for (const auto& delta : deltas) 42 | { 43 | RenderStudio::API::Event event { "Delta::Event", delta }; 44 | connection->Send(boost::json::serialize(boost::json::value_from(event))); 45 | } 46 | } 47 | 48 | // History sending finished 49 | RenderStudio::API::Event event { "History::Event", RenderStudio::API::HistoryEvent {} }; 50 | connection->Send(boost::json::serialize(boost::json::value_from(event))); 51 | 52 | DebugPrint(); 53 | } 54 | 55 | void 56 | Logic::OnDisconnected(ConnectionPtr connection) 57 | { 58 | // Thread safety 59 | std::lock_guard lock(mMutex); 60 | 61 | // Log 62 | LOG_INFO << "User \'" << connection->GetDebugName() << "\' exited \'" << connection->GetChannel() << "\'"; 63 | 64 | // Remove from channel 65 | if (mChannels.count(connection->GetChannel()) == 0) 66 | { 67 | LOG_ERROR << "User \'" << connection->GetDebugName() << "\' disconnected from non-existing channel \'" 68 | << connection->GetChannel() << "\'"; 69 | return; 70 | } 71 | 72 | Channel& channel = mChannels.at(connection->GetChannel()); 73 | channel.RemoveConnection(connection); 74 | 75 | if (channel.Empty()) 76 | { 77 | mChannels.erase(connection->GetChannel()); 78 | } 79 | 80 | DebugPrint(); 81 | } 82 | 83 | void 84 | Logic::OnMessage(ConnectionPtr connection, const std::string& message) 85 | { 86 | auto event = ParseEvent(message); 87 | if (!event.has_value()) 88 | { 89 | return; 90 | } 91 | 92 | std::visit( 93 | Overload { 94 | [&connection, this, &message](const RenderStudio::API::DeltaEvent& v) 95 | { 96 | // Thread safety 97 | std::lock_guard lock(mMutex); 98 | 99 | if (mChannels.count(connection->GetChannel()) == 0) 100 | { 101 | LOG_ERROR << "User \'" << connection->GetDebugName() 102 | << "\' sent message from non-existent channel \'" << connection->GetChannel() << "\'"; 103 | return; 104 | } 105 | 106 | // Process sequence 107 | Channel& channel = mChannels.at(connection->GetChannel()); 108 | std::size_t sequence = channel.GetSequenceNumber(v.layer); 109 | RenderStudio::API::DeltaEvent acknowledgedDelta = v; 110 | acknowledgedDelta.sequence = sequence; 111 | 112 | // Broadcast update to users 113 | channel.AddToHistory(acknowledgedDelta); 114 | channel.Send( 115 | connection, 116 | boost::json::serialize( 117 | boost::json::value_from(RenderStudio::API::Event { "Delta::Event", acknowledgedDelta }))); 118 | 119 | // Send acknowledge 120 | std::vector paths; 121 | 122 | for (const auto& [key, value] : v.updates) 123 | { 124 | paths.push_back(key); 125 | } 126 | 127 | RenderStudio::API::Event ack { "Acknowledge::Event", 128 | RenderStudio::API::AcknowledgeEvent { v.layer, paths, sequence } }; 129 | connection->Send(boost::json::serialize(boost::json::value_from(ack))); 130 | }, 131 | [](const RenderStudio::API::HistoryEvent& v) 132 | { 133 | (void)v; 134 | // Do nothing. Only clients receive history 135 | }, 136 | [](const RenderStudio::API::AcknowledgeEvent& v) 137 | { 138 | (void)v; 139 | // Do nothing. Only clients receive acknowledges 140 | }, 141 | [&connection, this, &message](const RenderStudio::API::ReloadEvent& v) 142 | { 143 | // Thread safety 144 | std::lock_guard lock(mMutex); 145 | 146 | if (mChannels.count(connection->GetChannel()) == 0) 147 | { 148 | LOG_ERROR << "User \'" << connection->GetDebugName() 149 | << "\' sent message from non-existent channel \'" << connection->GetChannel() << "\'"; 150 | return; 151 | } 152 | 153 | // Process sequence 154 | Channel& channel = mChannels.at(connection->GetChannel()); 155 | std::size_t sequence = channel.GetSequenceNumber(v.layer); 156 | RenderStudio::API::ReloadEvent acknowledgedReload = v; 157 | acknowledgedReload.sequence = sequence; 158 | 159 | // Broadcast update to users 160 | channel.ClearHistory(v.layer); 161 | channel.Send( 162 | connection, 163 | boost::json::serialize( 164 | boost::json::value_from(RenderStudio::API::Event { "Reload::Event", acknowledgedReload }))); 165 | } }, 166 | event.value().body); 167 | } 168 | 169 | void 170 | Logic::DebugPrint() const 171 | { 172 | if (mChannels.empty()) 173 | { 174 | return; 175 | } 176 | 177 | LOG_DEBUG << ":: Global channels stats ::"; 178 | for (const auto& [name, channel] : mChannels) 179 | { 180 | LOG_DEBUG << "Channel '" << name << "' stats"; 181 | LOG_DEBUG << " - Connected users: " << channel.GetConnections().size(); 182 | std::string layers = "["; 183 | for (auto it = channel.GetHistory().begin(); it != channel.GetHistory().end(); ++it) 184 | { 185 | layers += "(name: " + it->first + ", history: " + std::to_string(it->second.size()) + ")"; 186 | if (std::next(it) != channel.GetHistory().end()) 187 | { 188 | layers += ", "; 189 | } 190 | } 191 | layers += "]"; 192 | LOG_DEBUG << " - Used layers: " << layers; 193 | } 194 | } 195 | 196 | std::optional 197 | Logic::ParseEvent(const std::string& message) 198 | { 199 | try 200 | { 201 | boost::json::value json = boost::json::parse(message); 202 | return boost::json::value_to(json); 203 | } 204 | catch (const std::exception& ex) 205 | { 206 | LOG_WARNING << "Can't parse: [" << ex.what() << "]: " << message; 207 | return {}; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /Sources/Server/Logic.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "Channel.h" 18 | 19 | #include 20 | #include 21 | 22 | class Logic : public RenderStudio::Networking::IServerLogic 23 | { 24 | public: 25 | void OnConnected(ConnectionPtr connection) override; 26 | void OnDisconnected(ConnectionPtr connection) override; 27 | void OnMessage(ConnectionPtr connection, const std::string& message); 28 | 29 | private: 30 | void DebugPrint() const; 31 | std::optional ParseEvent(const std::string& message); 32 | 33 | std::map mChannels; 34 | std::mutex mMutex; 35 | }; 36 | -------------------------------------------------------------------------------- /Sources/Server/Main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma warning(push, 0) 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #pragma warning(pop) 23 | 24 | #include 25 | 26 | #include "Logic.h" 27 | 28 | #include 29 | #include 30 | 31 | auto 32 | main() -> int 33 | try 34 | { 35 | #ifdef PLATFORM_WINDOWS 36 | SetConsoleOutputCP(CP_UTF8); 37 | #endif 38 | 39 | #ifdef PLATFORM_UNIX 40 | std::locale::global(std::locale("en_US.UTF-8")); 41 | #endif 42 | 43 | const boost::asio::ip::address address = boost::asio::ip::make_address("0.0.0.0"); 44 | const std::uint16_t port = 52702; 45 | const std::int32_t threads = 10; 46 | 47 | RenderStudio::Kit::SetWorkspaceUrl("localhost"); 48 | RenderStudio::Kit::SharedWorkspaceConnect(RenderStudio::Kit::Role::Server); 49 | 50 | LOG_INFO << "Server started at " << address << ":" << port << " (threads: " << threads << ")"; 51 | 52 | boost::asio::io_context ioc { threads }; 53 | Logic logic; 54 | 55 | auto server = RenderStudio::Networking::WebsocketServer::Create( 56 | ioc, boost::asio::ip::tcp::endpoint { address, port }, logic); 57 | 58 | server->Run(); 59 | 60 | std::vector workers; 61 | workers.reserve(threads - 1); 62 | for (auto i = threads - 1; i > 0; --i) 63 | { 64 | workers.emplace_back([&ioc]() { ioc.run(); }); 65 | } 66 | ioc.run(); 67 | 68 | return EXIT_SUCCESS; 69 | } 70 | catch (const std::exception& ex) 71 | { 72 | LOG_FATAL << "[Server Fatal Exception] " << ex.what(); 73 | return EXIT_FAILURE; 74 | } 75 | -------------------------------------------------------------------------------- /Sources/Server/Run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | 4 | :: Get current script directory 5 | set SCRIPT_DIR="%~dp0" 6 | 7 | :: Prepare environment 8 | set USD_DIR=%~dp0.. 9 | set SERVICES_DIR=%USD_DIR%\.. 10 | set PYTHON_DIR=%SERVICES_DIR%\Engine\Standalone 11 | 12 | :: Setup environment 13 | set USD_PATH=%USD_DIR%\lib;%USD_DIR%\bin;%USD_DIR%\plugin\usd 14 | set PATH=%PATH%;%USD_PATH%;%PYTHON_DIR% 15 | 16 | :: Launch server 17 | "%~dp0\RenderStudioServer.exe" %* 18 | -------------------------------------------------------------------------------- /Sources/Server/Run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get current script directory 4 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 5 | PARENT_DIR="$(dirname "$SCRIPT_DIR")" 6 | 7 | # Launch server 8 | LD_LIBRARY_PATH=$PARENT_DIR/lib $SCRIPT_DIR/RenderStudioServer 9 | -------------------------------------------------------------------------------- /Sources/Utils/BackgroundTask.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "BackgroundTask.h" 16 | 17 | namespace RenderStudio::Utils 18 | { 19 | 20 | BackgroundTask::BackgroundTask(TaskFn task, std::uint32_t interval) 21 | : mTask(task) 22 | , mInterval(interval) 23 | { 24 | } 25 | 26 | BackgroundTask::~BackgroundTask() { Stop(); } 27 | 28 | void 29 | BackgroundTask::Start() 30 | { 31 | std::unique_lock lock(mMutex); 32 | 33 | if (mRunning) 34 | { 35 | return; 36 | } 37 | 38 | mRunning = true; 39 | mThread = std::thread(&BackgroundTask::Run, this); 40 | } 41 | 42 | void 43 | BackgroundTask::Stop() 44 | { 45 | std::unique_lock lock(mMutex); 46 | 47 | if (!mRunning) 48 | { 49 | return; 50 | } 51 | 52 | mRunning = false; 53 | lock.unlock(); 54 | mCondition.notify_one(); 55 | 56 | if (mThread.joinable()) 57 | { 58 | mThread.join(); 59 | } 60 | } 61 | 62 | void 63 | BackgroundTask::Run() 64 | { 65 | while (IsRunning()) 66 | { 67 | mTask(); 68 | 69 | std::unique_lock lock(mMutex); 70 | mCondition.wait_for(lock, std::chrono::seconds(mInterval), [this] { return !mRunning; }); 71 | } 72 | } 73 | 74 | bool 75 | BackgroundTask::IsRunning() const 76 | { 77 | std::lock_guard lock(mMutex); 78 | return mRunning; 79 | } 80 | 81 | } // namespace RenderStudio::Utils 82 | -------------------------------------------------------------------------------- /Sources/Utils/BackgroundTask.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace RenderStudio::Utils 23 | { 24 | 25 | class BackgroundTask 26 | { 27 | public: 28 | using TaskFn = std::function; 29 | 30 | BackgroundTask(TaskFn task, std::uint32_t interval); 31 | ~BackgroundTask(); 32 | 33 | void Start(); 34 | void Stop(); 35 | 36 | private: 37 | void Run(); 38 | bool IsRunning() const; 39 | 40 | TaskFn mTask; 41 | bool mRunning { false }; 42 | mutable std::mutex mMutex; 43 | std::condition_variable mCondition; 44 | std::thread mThread; 45 | std::uint32_t mInterval { 0 }; 46 | }; 47 | 48 | } // namespace RenderStudio::Utils 49 | -------------------------------------------------------------------------------- /Sources/Utils/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 3.12) 16 | set(KIT_TARGET_NAME "RenderStudioUtils") 17 | 18 | set(CMAKE_CXX_STANDARD 20) 19 | 20 | # Create target 21 | file(GLOB SOURCES *.h *.cpp) 22 | add_library(${KIT_TARGET_NAME} STATIC ${SOURCES}) 23 | 24 | # Link libraries 25 | target_link_libraries(${KIT_TARGET_NAME} PRIVATE 26 | RenderStudioLogger 27 | zip::zip 28 | ) 29 | 30 | target_include_directories(${KIT_TARGET_NAME} PRIVATE ..) 31 | 32 | SetDefaultCompileDefinitions(${KIT_TARGET_NAME}) 33 | SetMaxWarningLevel(${KIT_TARGET_NAME}) 34 | -------------------------------------------------------------------------------- /Sources/Utils/FileUtils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "FileUtils.h" 16 | 17 | #ifdef PLATFORM_WINDOWS 18 | #include 19 | #include 20 | #endif 21 | 22 | #pragma warning(push, 0) 23 | #include 24 | #pragma warning(pop) 25 | 26 | #include 27 | #include 28 | 29 | namespace RenderStudio::Utils 30 | { 31 | 32 | std::filesystem::path 33 | GetUserHomePath() 34 | { 35 | #ifdef PLATFORM_WINDOWS 36 | std::string useLegacyFolder = "OFF"; 37 | 38 | auto GetEnironmentImpl = [](const std::string& name) 39 | { 40 | const DWORD size = GetEnvironmentVariable(name.c_str(), nullptr, 0); 41 | if (size != 0) 42 | { 43 | std::unique_ptr buffer(new char[size]); 44 | GetEnvironmentVariable(name.c_str(), buffer.get(), size); 45 | return std::string(buffer.get()); 46 | } 47 | else 48 | { 49 | return std::string(); 50 | } 51 | }; 52 | 53 | if (!GetEnironmentImpl("RENDER_STUDIO_USE_LEGACY_FOLDER").empty()) 54 | { 55 | useLegacyFolder = GetEnironmentImpl("RENDER_STUDIO_USE_LEGACY_FOLDER"); 56 | } 57 | 58 | if (useLegacyFolder == "ON") 59 | { 60 | LOG_FATAL << "Using legacy windows folder in ProgramData"; 61 | 62 | PWSTR path = nullptr; 63 | HRESULT hr = SHGetKnownFolderPath(FOLDERID_ProgramData, 0, NULL, &path); 64 | if (SUCCEEDED(hr)) 65 | { 66 | std::filesystem::path result(path); 67 | CoTaskMemFree(path); 68 | return result; 69 | } 70 | return {}; 71 | } 72 | else 73 | { 74 | PWSTR path = nullptr; 75 | HRESULT hr = SHGetKnownFolderPath(FOLDERID_Profile, 0, NULL, &path); 76 | if (SUCCEEDED(hr)) 77 | { 78 | std::filesystem::path result(path); 79 | CoTaskMemFree(path); 80 | return result; 81 | } 82 | return {}; 83 | } 84 | #endif 85 | 86 | #ifdef PLATFORM_UNIX 87 | return std::filesystem::path("/var/lib/AMD/"); 88 | #endif 89 | } 90 | 91 | std::filesystem::path 92 | GetDefaultWorkspacePath() 93 | { 94 | std::filesystem::path workspacePath = GetRenderStudioPath() / "Workspace"; 95 | std::filesystem::path syncthingPath = GetRenderStudioPath() / "Syncthing"; 96 | std::filesystem::path markerPath = GetRenderStudioPath() / "Workspace" / ".stfolder"; 97 | 98 | // When marker is missing, remove all syncthing database to resync 99 | if (!std::filesystem::exists(markerPath)) 100 | { 101 | std::filesystem::remove_all(syncthingPath); 102 | std::filesystem::create_directories(markerPath); 103 | } 104 | 105 | return workspacePath; 106 | } 107 | 108 | std::filesystem::path 109 | GetRenderStudioPath() 110 | { 111 | std::filesystem::path path = GetUserHomePath() / "AMD RenderStudio"; 112 | 113 | if (!std::filesystem::exists(path)) 114 | { 115 | std::filesystem::create_directories(path); 116 | } 117 | 118 | return path; 119 | } 120 | 121 | TempDirectory::TempDirectory() 122 | { 123 | std::filesystem::path path; 124 | 125 | do 126 | { 127 | path = GetRenderStudioPath() / "Temp" / RenderStudio::Utils::GenerateUUID(); 128 | } while (std::filesystem::exists(path)); 129 | 130 | std::filesystem::create_directories(path); 131 | mPath = path; 132 | LOG_INFO << "Create temp dir: " << mPath; 133 | } 134 | 135 | TempDirectory::~TempDirectory() 136 | { 137 | if (std::filesystem::exists(mPath)) 138 | { 139 | std::filesystem::remove_all(mPath); 140 | } 141 | } 142 | 143 | std::filesystem::path 144 | TempDirectory::Path() const 145 | { 146 | return mPath; 147 | } 148 | 149 | void 150 | Extract(const std::filesystem::path& archive, const std::filesystem::path& destination) 151 | { 152 | if (!std::filesystem::exists(destination)) 153 | { 154 | std::filesystem::create_directories(destination); 155 | } 156 | 157 | int arg = 0; 158 | auto status = zip_extract( 159 | archive.string().c_str(), 160 | destination.string().c_str(), 161 | [](auto a, auto b) 162 | { 163 | (void)a, void(b); 164 | return 0; 165 | }, 166 | &arg); 167 | 168 | if (status != 0) 169 | { 170 | LOG_ERROR << "Cant extract " << archive << " to " << destination << ", error: " << status; 171 | } 172 | } 173 | 174 | void 175 | Move(const std::filesystem::path& source, const std::filesystem::path& destination) 176 | { 177 | if (!std::filesystem::exists(destination)) 178 | { 179 | std::filesystem::create_directories(destination); 180 | } 181 | 182 | for (std::filesystem::path p : std::filesystem::directory_iterator(source)) 183 | { 184 | std::filesystem::rename(p, destination / p.filename()); 185 | } 186 | } 187 | 188 | std::filesystem::path 189 | GetCachePath() 190 | { 191 | std::filesystem::path path = GetRenderStudioPath() / "Cache"; 192 | 193 | if (!std::filesystem::exists(path)) 194 | { 195 | std::filesystem::create_directories(path); 196 | } 197 | 198 | return path; 199 | } 200 | 201 | } // namespace RenderStudio::Utils 202 | -------------------------------------------------------------------------------- /Sources/Utils/FileUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | namespace RenderStudio::Utils 18 | { 19 | 20 | class TempDirectory 21 | { 22 | public: 23 | TempDirectory(); 24 | ~TempDirectory(); 25 | std::filesystem::path Path() const; 26 | 27 | private: 28 | std::filesystem::path mPath; 29 | }; 30 | 31 | std::filesystem::path GetUserHomePath(); 32 | std::filesystem::path GetDefaultWorkspacePath(); 33 | std::filesystem::path GetRenderStudioPath(); 34 | std::filesystem::path GetCachePath(); 35 | void Extract(const std::filesystem::path& archive, const std::filesystem::path& destination); 36 | void Move(const std::filesystem::path& source, const std::filesystem::path& destination); 37 | 38 | } // namespace RenderStudio::Utils 39 | -------------------------------------------------------------------------------- /Sources/Utils/ProcessUtils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "ProcessUtils.h" 16 | 17 | #ifdef PLATFORM_WINDOWS 18 | #include 19 | #include 20 | #include 21 | #pragma comment(lib, "shell32.lib") 22 | #endif 23 | 24 | #ifdef PLATFORM_UNIX 25 | #include 26 | #include 27 | #include 28 | #endif 29 | 30 | #include 31 | 32 | #include 33 | 34 | namespace RenderStudio::Utils 35 | { 36 | 37 | #ifdef PLATFORM_UNIX 38 | void 39 | LaunchProcess(std::filesystem::path apppication, const std::vector& args) 40 | { 41 | std::string app = apppication.make_preferred().string(); 42 | std::string arg = boost::algorithm::join(args, " "); 43 | 44 | std::vector argv; 45 | 46 | wordexp_t p; 47 | if (wordexp((app + " " + arg).c_str(), &p, 0)) 48 | { 49 | throw std::runtime_error("Could not create child process"); 50 | } 51 | 52 | for (std::size_t i = 0; i < p.we_wordc; i++) 53 | { 54 | argv.push_back(p.we_wordv[i]); 55 | } 56 | 57 | argv.push_back(nullptr); 58 | 59 | pid_t pid; 60 | int status = posix_spawn(&pid, app.c_str(), nullptr, nullptr, argv.data(), environ); 61 | 62 | if (status != 0) 63 | { 64 | throw std::runtime_error("Could not create child process"); 65 | } 66 | } 67 | #endif 68 | 69 | #ifdef PLATFORM_WINDOWS 70 | void 71 | LaunchProcess(std::filesystem::path application, const std::vector& args) 72 | { 73 | std::string app = application.make_preferred().string(); 74 | std::string arg = boost::algorithm::join(args, " "); 75 | 76 | // Prepare handles. 77 | STARTUPINFOW si; 78 | PROCESS_INFORMATION pi; // The function returns this 79 | ZeroMemory(&si, sizeof(si)); 80 | si.cb = sizeof(si); 81 | ZeroMemory(&pi, sizeof(pi)); 82 | 83 | // Prepare CreateProcess args 84 | std::wstring app_w; 85 | Widen(app, app_w); 86 | 87 | std::wstring arg_w; 88 | Widen(arg, arg_w); 89 | 90 | std::wstring input = L"\"" + app_w + L"\" " + arg_w; 91 | wchar_t* arg_concat = const_cast(input.c_str()); 92 | const wchar_t* app_const = app_w.c_str(); 93 | 94 | // Start the child process. 95 | if (!CreateProcessW( 96 | app_const, // app path 97 | arg_concat, // Command line (needs to include app path as first argument. args seperated by whitepace) 98 | NULL, // Process handle not inheritable 99 | NULL, // Thread handle not inheritable 100 | FALSE, // Set handle inheritance to FALSE 101 | 0, // No creation flags 102 | NULL, // Use parent's environment block 103 | NULL, // Use parent's starting directory 104 | &si, // Pointer to STARTUPINFO structure 105 | &pi) // Pointer to PROCESS_INFORMATION structure 106 | ) 107 | { 108 | throw std::exception("Could not create child process"); 109 | } 110 | } 111 | 112 | // helper to widen a narrow UTF8 string in Win32 113 | const wchar_t* 114 | Widen(const std::string& narrow, std::wstring& wide) 115 | { 116 | size_t length = narrow.size(); 117 | 118 | if (length > 0) 119 | { 120 | wide.resize(length); 121 | length = MultiByteToWideChar(CP_UTF8, 0, narrow.c_str(), (int)length, (wchar_t*)wide.c_str(), (int)length); 122 | wide.resize(length); 123 | } 124 | else 125 | { 126 | wide.clear(); 127 | } 128 | 129 | return wide.c_str(); 130 | } 131 | #endif 132 | 133 | } // namespace RenderStudio::Utils 134 | -------------------------------------------------------------------------------- /Sources/Utils/ProcessUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | namespace RenderStudio::Utils 19 | { 20 | 21 | void LaunchProcess(std::filesystem::path application, const std::vector& args); 22 | 23 | #ifdef PLATFORM_WINDOWS 24 | const wchar_t* Widen(const std::string& narrow, std::wstring& wide); 25 | #endif 26 | 27 | } // namespace RenderStudio::Utils 28 | -------------------------------------------------------------------------------- /Sources/Utils/Uuid.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "Uuid.h" 16 | 17 | #include 18 | #include 19 | 20 | namespace RenderStudio::Utils 21 | { 22 | 23 | // Thank you for implementation 24 | // https://stackoverflow.com/questions/24365331/how-can-i-generate-uuid-in-c-without-using-boost-library 25 | 26 | std::string 27 | GenerateUUID() 28 | { 29 | std::random_device rd; 30 | std::mt19937 gen(rd()); 31 | std::uniform_int_distribution<> dis(0, 15); 32 | std::uniform_int_distribution<> dis2(8, 11); 33 | 34 | std::stringstream ss; 35 | int i; 36 | ss << std::hex; 37 | 38 | for (i = 0; i < 8; i++) 39 | { 40 | ss << dis(gen); 41 | } 42 | 43 | ss << "-"; 44 | 45 | for (i = 0; i < 4; i++) 46 | { 47 | ss << dis(gen); 48 | } 49 | 50 | ss << "-4"; 51 | 52 | for (i = 0; i < 3; i++) 53 | { 54 | ss << dis(gen); 55 | } 56 | 57 | ss << "-"; 58 | ss << dis2(gen); 59 | 60 | for (i = 0; i < 3; i++) 61 | { 62 | ss << dis(gen); 63 | } 64 | 65 | ss << "-"; 66 | 67 | for (i = 0; i < 12; i++) 68 | { 69 | ss << dis(gen); 70 | }; 71 | 72 | return ss.str(); 73 | } 74 | 75 | } // namespace RenderStudio::Utils 76 | -------------------------------------------------------------------------------- /Sources/Utils/Uuid.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Advanced Micro Devices, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | 19 | namespace RenderStudio::Utils 20 | { 21 | 22 | std::string GenerateUUID(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Tools/Dockerfile.Builder: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | ENV DEBIAN_FRONTEND="noninteractive" 4 | RUN apt-get update && \ 5 | apt-get install -y --no-install-recommends && \ 6 | apt-get install -y python3 \ 7 | python3-distutils \ 8 | build-essential \ 9 | cmake \ 10 | git \ 11 | ca-certificates \ 12 | gpg \ 13 | wget \ 14 | libpython3-dev \ 15 | libx11-dev \ 16 | libgl1-mesa-dev \ 17 | mc \ 18 | patchelf \ 19 | zlib1g-dev \ 20 | libssl-dev \ 21 | libglu1-mesa-dev \ 22 | freeglut3-dev \ 23 | mesa-common-dev \ 24 | python3-pip \ 25 | libxt-dev && \ 26 | rm -rf /var/lib/apt/lists/* && \ 27 | wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | \ 28 | gpg --dearmor - | \ 29 | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null && \ 30 | echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | \ 31 | tee /etc/apt/sources.list.d/kitware.list >/dev/null && \ 32 | apt-get update && \ 33 | rm /usr/share/keyrings/kitware-archive-keyring.gpg && \ 34 | apt-get install -y kitware-archive-keyring cmake 35 | 36 | ENV DEBIAN_FRONTEND="interactive" 37 | 38 | WORKDIR /mnt 39 | CMD mkdir -p Build && \ 40 | echo "[WebRTC]\npath = /dev/null\n[AMF]\npath = /dev/null" > Build/LocalBuildConfig.txt && \ 41 | python3 -u Tools/Build.py -v -ss -sr -sl -sh -sst -sp -su -fk && \ 42 | bash -c "cp /usr/lib/x86_64-linux-gnu/libpython* Build/Install/USD/lib" && \ 43 | bash -c "cp /usr/lib/x86_64-linux-gnu/libssl* Build/Install/USD/lib" && \ 44 | bash -c "cp /usr/lib/x86_64-linux-gnu/libcrypto* Build/Install/USD/lib" 45 | -------------------------------------------------------------------------------- /Tools/Dockerfile.Tester: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | ENV DEBIAN_FRONTEND="noninteractive" 4 | RUN apt-get update && \ 5 | apt-get install -y --no-install-recommends && \ 6 | apt-get install -y python3 \ 7 | python3-distutils \ 8 | build-essential \ 9 | cmake \ 10 | git \ 11 | ca-certificates \ 12 | gpg \ 13 | wget \ 14 | libpython3-dev \ 15 | libx11-dev \ 16 | libgl1-mesa-dev \ 17 | mc \ 18 | patchelf \ 19 | zlib1g-dev \ 20 | libssl-dev \ 21 | libglu1-mesa-dev \ 22 | freeglut3-dev \ 23 | mesa-common-dev \ 24 | python3-pip \ 25 | libxt-dev && \ 26 | rm -rf /var/lib/apt/lists/* && \ 27 | wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | \ 28 | gpg --dearmor - | \ 29 | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null && \ 30 | echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | \ 31 | tee /etc/apt/sources.list.d/kitware.list >/dev/null && \ 32 | apt-get update && \ 33 | rm /usr/share/keyrings/kitware-archive-keyring.gpg && \ 34 | apt-get install -y kitware-archive-keyring cmake 35 | 36 | ENV DEBIAN_FRONTEND="interactive" 37 | 38 | WORKDIR /mnt 39 | CMD bash Kit/Examples/run.sh 40 | -------------------------------------------------------------------------------- /Tools/Makefile: -------------------------------------------------------------------------------- 1 | ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) 2 | PROJECT_DIR := $(ROOT_DIR)/../.. 3 | 4 | build: 5 | docker build -t render-studio-builder-image -f Dockerfile.Builder . 6 | docker run --rm -v $(PROJECT_DIR):/mnt/ --name render-studio-builder-container render-studio-builder-image 7 | 8 | test: 9 | docker build -t render-studio-tester-image -f Dockerfile.Tester . 10 | docker run --rm -v $(PROJECT_DIR):/mnt/ -v $(PROJECT_DIR)/SyncthingTest/:/var/lib/AMD/ --name render-studio-tester-container render-studio-tester-image 11 | 12 | deploy: 13 | rsync -azP --delete $(PROJECT_DIR)/Build/Install/USD/* studio:/opt/rs/ 14 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.2.0 2 | -------------------------------------------------------------------------------- /Workspace/RenderStudioWorkspace.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import argparse 16 | import uvicorn 17 | import sys 18 | 19 | from app.logger import logger 20 | from app.settings import settings 21 | 22 | if __name__ == '__main__': 23 | parser = argparse.ArgumentParser(description="AMD RenderStudio workspace service", allow_abbrev=False) 24 | parser.add_argument('-p', '--port', help="Port for workspace", type=int, required=False, default=52700) 25 | parser.add_argument('-i', '--ping-interval', help="Required ping interval", type=int, required=False, default=10) 26 | parser.add_argument('-s', '--syncthing-url', help="Syncthing API url", type=str, required=False, default="http://127.0.0.1:52701") 27 | parser.add_argument('-r', '--remote-url', help="Remote Syncthing API url", type=str, required=True) 28 | parser.add_argument('-k', '--syncthing-api-key', help="Local Syncthing API key", type=str, required=False, default="render-studio-key") 29 | parser.add_argument('-w', '--workspace', help="Syncthing API key", type=str, required=True) 30 | args = parser.parse_args() 31 | 32 | settings.REQUIRED_PING_INTERVAL_SECONDS = args.ping_interval 33 | settings.WEBSOCKET_PORT = args.port 34 | settings.SYNCTHING_URL = args.syncthing_url 35 | settings.SYNCTHING_API_KEY = args.syncthing_api_key 36 | settings.WORKSPACE_DIR = args.workspace 37 | settings.REMOTE_URL = args.remote_url 38 | 39 | for key, value in settings.get_declared_fields().items(): 40 | logger.info(f"{key}: {value}") 41 | 42 | import app.main 43 | uvicorn.run("app.main:app", port=settings.WEBSOCKET_PORT, log_level="warning") 44 | -------------------------------------------------------------------------------- /Workspace/app/logger.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import logging 16 | 17 | LOGGING_CONFIG = { 18 | "version": 1, 19 | "handlers": { 20 | "default": { 21 | "class": "logging.StreamHandler", 22 | "formatter": "workspace", 23 | "stream": "ext://sys.stderr" 24 | }, 25 | "syncthing": { 26 | "class": "logging.StreamHandler", 27 | "formatter": "syncthing", 28 | "stream": "ext://sys.stderr" 29 | } 30 | }, 31 | "formatters": { 32 | "workspace": { 33 | "format": "\033[94m[workspace]\033[0m %(message)s", 34 | "datefmt": "%H:%M:%S", 35 | }, 36 | "syncthing": { 37 | "format": "\033[95m[syncthing]\033[0m %(message)s", 38 | "datefmt": "%H:%M:%S", 39 | } 40 | }, 41 | 'loggers': { 42 | 'httpx': { 43 | 'handlers': ['default'], 44 | 'level': 'WARN', 45 | }, 46 | 'httpcore': { 47 | 'handlers': ['default'], 48 | 'level': 'WARN', 49 | }, 50 | 'default': { 51 | 'handlers': ['default'], 52 | 'level': 'INFO', 53 | }, 54 | 'syncthing': { 55 | 'handlers': ['syncthing'], 56 | 'level': 'INFO', 57 | } 58 | } 59 | } 60 | 61 | logging.config.dictConfig(LOGGING_CONFIG) 62 | logger = logging.getLogger('default') 63 | syncthing_logger = logging.getLogger('syncthing') 64 | -------------------------------------------------------------------------------- /Workspace/app/main.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from fastapi import FastAPI, WebSocket, WebSocketDisconnect 16 | from pydantic import BaseModel 17 | import asyncio 18 | import sys 19 | 20 | from app.logger import logger 21 | from app.settings import settings 22 | from app.syncthing_manager import syncthing_manager 23 | from app.connection_manager import connection_manager 24 | 25 | app = FastAPI() 26 | 27 | @app.on_event("startup") 28 | async def startup_event(): 29 | logger.info("Startup event which should check remote") 30 | 31 | @app.websocket("/workspace/ws") 32 | async def watchdog(websocket: WebSocket): 33 | await connection_manager.connect(websocket) 34 | try: 35 | while True: 36 | await connection_manager.receive_text(websocket) 37 | except WebSocketDisconnect: 38 | await connection_manager.disconnect(websocket) 39 | 40 | class ConnectionInfo(BaseModel): 41 | device_id: str 42 | 43 | @app.get("/workspace/info") 44 | async def info(): 45 | device = await syncthing_manager.get_device() 46 | config = await syncthing_manager.get_config() 47 | return { 48 | 'device_id': device['deviceID'], 49 | 'device_name': device['name'], 50 | 'folder_id': config['folders'][0]['id'], 51 | 'folder_name': config['folders'][0]['label'] 52 | } 53 | 54 | @app.post("/workspace/connect") 55 | async def connect(info: ConnectionInfo): 56 | # Legacy method for backward compatibility 57 | return {'status': 'ok'} 58 | -------------------------------------------------------------------------------- /Workspace/app/settings.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from threading import Lock 16 | 17 | class Settings: 18 | REQUIRED_PING_INTERVAL_SECONDS: int = None 19 | WEBSOCKET_PORT: int = None 20 | SYNCTHING_URL: str = None 21 | REMOTE_URL: str = None 22 | SYNCTHING_API_KEY: str = None 23 | WORKSPACE_DIR: str = None 24 | 25 | def get_declared_fields(self): 26 | class_annotations = self.__annotations__ 27 | return {field: getattr(self, field) for field in class_annotations} 28 | 29 | settings = Settings() 30 | -------------------------------------------------------------------------------- /Workspace/app/terminator.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Advanced Micro Devices, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import traceback 17 | 18 | class Terminator: 19 | async def terminate_all(self): 20 | from app.logger import logger 21 | logger.info('[Terminator] TERMINATE ALL CALLED') 22 | 23 | try: 24 | from app.syncthing_manager import syncthing_manager 25 | await syncthing_manager.terminate() 26 | except Exception as e: 27 | logger.error(f"[Terminator] Syncthing: {traceback.format_exc()} (that should be fine)") 28 | 29 | try: 30 | from app.connection_manager import connection_manager 31 | await connection_manager.terminate() 32 | except Exception as e: 33 | logger.error(f"[Terminator] Websocket: {traceback.format_exc()} (that should be fine)") 34 | 35 | logger.info('Bye-bye') 36 | os._exit(1) 37 | 38 | terminator = Terminator() 39 | -------------------------------------------------------------------------------- /Workspace/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.103.2 2 | uvicorn==0.22.0 3 | pyinstaller==5.13.2 4 | pyinstaller-hooks-contrib==2023.10 5 | websockets==10.4 6 | httpx==0.24.1 7 | nuitka==1.8.5 8 | --------------------------------------------------------------------------------