-
Notifications
You must be signed in to change notification settings - Fork 23
/
main.cpp
220 lines (186 loc) · 7.46 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
// clang-format off
#include <iostream>
#include <cstdlib>
#ifdef WANTS_PYTHON
#include <Python.h>
#endif
#include <pxr/base/plug/registry.h>
#include <pxr/base/arch/env.h>
#include <pxr/base/arch/systemInfo.h>
#include <pxr/imaging/glf/contextCaps.h>
#include <pxr/imaging/glf/simpleLight.h>
#include <pxr/imaging/glf/diagnostic.h>
#include "Editor.h"
#include "Viewport.h"
#include "Commands.h"
#include "Constants.h"
#include "ResourcesLoader.h"
#include "CommandLineOptions.h"
#include "Gui.h"
#ifdef _WIN64
#include<process.h>
#endif
// clang-format on
// Select high performance GPU on multi GPU platforms, (laptops, vm, etc.)
extern "C"
{
// NVidia GPUs
// see: https://stackoverflow.com/questions/10535950/forcing-nvidia-gpu-programmatically-in-optimus-laptops/14041061#14041061
ARCH_EXPORT unsigned long NvOptimusEnablement = 0x00000001;
// AMD GPUs
// see: https://stackoverflow.com/questions/17458803/amd-equivalent-to-nvoptimusenablement
ARCH_EXPORT int AmdPowerXpressRequestHighPerformance = 1;
}
PXR_NAMESPACE_USING_DIRECTIVE
// https://learn.microsoft.com/en-us/windows/win32/procthread/changing-environment-variables
#ifdef _WIN64
static std::vector<char *> ArchCurrentEnviron() {
std::vector<char *> newEnv;
for (char *envIt = GetEnvironmentStrings(); *envIt; envIt++) {
newEnv.push_back(envIt);
while (*envIt != 0) {
envIt++;
}
}
newEnv.push_back(0); // The last element must be the null pointer
return newEnv;
}
#endif
static bool InstallApplicationPluginPaths(const std::vector<std::string> &pluginPaths) {
const char *BOOTSTRAPPED = "USDTWEAK_BOOTSTRAPPED";
if (!pluginPaths.empty() && !ArchHasEnv(BOOTSTRAPPED)) {
if (!ArchSetEnv(BOOTSTRAPPED, "1", true)) {
return false;
}
ArchSetEnv("PXR_PLUGINPATH_NAME", TfStringJoin(pluginPaths.begin(), pluginPaths.end(), ";"), true);
return true;
}
return false;
}
int main(int argc, char *const *argv) {
CommandLineOptions options(argc, argv);
// ResourceLoader will load the settings/fonts/textures and create an imgui context
ResourcesLoader loader;
// Adding the plugin paths specified in the config file to the environment. It potentially means restarting the
// application with a new environment. Unfortunately USD is not able to dynamically load plugin
// functionalities after startup time, the functions like RegisterPlugins or Load simply does not
// do what one would expect, more there:
// https://groups.google.com/g/usd-interest/c/fpLYyf6elmU/m/haZf9bZDAgAJ
// So the only option I see is to reload the application with an updated environment
if (InstallApplicationPluginPaths(loader.GetEditorSettings()._pluginPaths)) {
std::cout << "Reloading application with new environment" << std::endl;
std::string exePath = ArchGetExecutablePath();
#ifndef _WIN64
execve(exePath.c_str(), argv, ArchEnviron());
#else
// Unfortunately ArchEnviron() doesn't return the modified environment on windows, we need to copy the current env
_execve(exePath.c_str(), argv, ArchCurrentEnviron().data());
#endif
}
// Initialize python
#ifdef WANTS_PYTHON
Py_SetProgramName(argv[0]);
Py_Initialize();
#endif
// Initialize glfw
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#else
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
#endif
/* Create a windowed mode window and its OpenGL context */
int width = loader.GetApplicationWidth();
int height = loader.GetApplicationHeight();
#ifdef DISABLE_DOUBLE_BUFFER
glfwWindowHint(GLFW_DOUBLEBUFFER, GL_FALSE);
#endif
GLFWwindow *window = glfwCreateWindow(width, height, "usdtweak", NULL, NULL);
if (!window) {
std::cerr << "unable to create a window, exiting" << std::endl;
glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Init glew with USD
GarchGLApiLoad();
GlfContextCaps::InitInstance();
std::cout << glGetString(GL_VENDOR) << std::endl;
std::cout << glGetString(GL_RENDERER) << std::endl;
std::cout << "OpenGL " << glGetString(GL_VERSION) << std::endl;
std::cout << "GLSL " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
std::cout << "USD " << PXR_VERSION << std::endl;
#if (__APPLE__ && PXR_VERSION < 2208)
std::cout << "Viewport is disabled on Apple platform with USD < 22.08" << std::endl;
#endif
const char *pluginPathName = std::getenv("PXR_PLUGINPATH_NAME");
std::cout << "PXR_PLUGINPATH_NAME: " << (pluginPathName ? pluginPathName : "") << std::endl;
// Init ImGui for glfw and opengl
ImGuiContext *mainUIContext = ImGui::GetCurrentContext();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init();
// Init an imgui context for hydra, to render the gizmo and hud
ImGuiContext *hydraUIContext = ImGui::CreateContext();
ImGui::SetCurrentContext(hydraUIContext);
ImGui_ImplOpenGL3_Init();
{ // we use a scope as the editor should be deleted before imgui and glfw, to release correctly the memory
ImGui::SetCurrentContext(mainUIContext);
Editor editor;
// Connect the window callbacks to the editor
editor.InstallCallbacks(window);
// Process command line options
for (auto &stage : options.stages()) {
editor.OpenStage(stage);
}
// Loop until the user closes the window
while (!editor.IsShutdown()) {
// Poll and process events
glfwMakeContextCurrent(window);
glfwPollEvents();
// Render the viewports first as textures
ImGui_ImplGlfw_RestoreCallbacks(window);
ImGui::SetCurrentContext(hydraUIContext);
editor.HydraRender(); // RenderViewports
// Render GUI next
ImGui::SetCurrentContext(mainUIContext);
ImGui_ImplGlfw_InstallCallbacks(window);
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
editor.Draw();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#ifndef DISABLE_DOUBLE_BUFFER
// Swap front and back buffers
glfwSwapBuffers(window);
#else
glFlush();
#endif
// This forces to wait for the gpu commands to finish.
// Normally not required but it fixes a pcoip driver issue
glFinish();
// Process edition commands
ExecuteCommands();
}
editor.RemoveCallbacks(window);
}
ImGui::DestroyContext(hydraUIContext);
// Shutdown imgui
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
// Shutdown glfw
glfwDestroyWindow(window);
glfwTerminate();
#ifdef WANTS_PYTHON
Py_Finalize();
#endif
return 0;
}