1
2
3#pragma once
4
5#include <string>
6#include <iostream>
7#include <stdexcept>
8#include <stdio.h>
9#include <iostream>
10#include <fstream>
11#include <stdexcept>
12#include <algorithm>
13#include <chrono>
14#include <vector>
15#include <cstring>
16#include <cstdlib>
17#include <cstdint>
18#include <array>
19#include <optional>
20#include <set>
21#include <unordered_map>
22
23#ifdef _WIN64
24#include <aclapi.h>
25#include <dxgi1_2.h>
26#include <windows.h>
27#include <VersionHelpers.h>
28#define _USE_MATH_DEFINES
29#endif
30
31#ifdef _WIN64
32#define VK_USE_PLATFORM_WIN32_KHR 1
33#endif
34
35#include "taichi/rhi/vulkan/vulkan_common.h"
36#include "taichi/rhi/window_system.h"
37
38#include <stdarg.h>
39
40#define GLM_FORCE_DEPTH_ZERO_TO_ONE
41#include <glm/glm.hpp>
42#include <glm/gtc/matrix_transform.hpp>
43#include <glm/gtc/type_ptr.hpp>
44
45namespace taichi::ui {
46
47#define RHI_VERIFY(rhi_call) \
48 { \
49 taichi::lang::RhiResult r = rhi_call; \
50 TI_ASSERT_INFO(r == taichi::lang::RhiResult::success, \
51 "`{}` failed, error {}", #rhi_call, int(r)); \
52 }
53
54#ifdef TI_WITH_GLFW
55inline GLFWwindow *create_glfw_window_(const std::string &name,
56 int screenWidth,
57 int screenHeight,
58 int window_pos_x,
59 int window_pos_y,
60 bool vsync) {
61 if (!taichi::lang::window_system::glfw_context_acquire()) {
62 printf("cannot initialize GLFW\n");
63 exit(EXIT_FAILURE);
64 }
65 GLFWwindow *window;
66
67 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
68 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
69
70 window = glfwCreateWindow(screenWidth, screenHeight, name.c_str(), nullptr,
71 nullptr);
72
73 if (!window) {
74 taichi::lang::window_system::glfw_context_release();
75 exit(EXIT_FAILURE);
76 }
77
78 if (glfwVulkanSupported() != GLFW_TRUE) {
79 printf("GLFW reports no Vulkan support\n");
80 }
81
82 // Reset the window hints to default
83 glfwDefaultWindowHints();
84
85 glfwSetWindowPos(window, window_pos_x, window_pos_y);
86
87 glfwShowWindow(window);
88 // Invalid for Vulkan
89 /*
90 if (vsync) {
91 glfwSwapInterval(1);
92 } else {
93 glfwSwapInterval(0);
94 }
95 */
96 return window;
97}
98
99struct Keys {
100#define DEFINE_KEY(name) static inline const std::string name = #name
101
102 DEFINE_KEY(Shift);
103 DEFINE_KEY(Alt);
104 DEFINE_KEY(Control);
105 DEFINE_KEY(Escape);
106 DEFINE_KEY(Return);
107 DEFINE_KEY(Tab);
108 DEFINE_KEY(BackSpace);
109 static inline const std::string Space = " ";
110 DEFINE_KEY(Up);
111 DEFINE_KEY(Down);
112 DEFINE_KEY(Left);
113 DEFINE_KEY(Right);
114 DEFINE_KEY(CapsLock);
115 DEFINE_KEY(LMB);
116 DEFINE_KEY(MMB);
117 DEFINE_KEY(RMB);
118#undef DEFINE_KEY
119};
120
121inline std::unordered_map<std::string, int> get_keys_map() {
122 static std::unordered_map<std::string, int> keys = {
123 {Keys::Shift, GLFW_KEY_LEFT_SHIFT},
124 {Keys::Alt, GLFW_KEY_LEFT_ALT},
125 {Keys::Control, GLFW_KEY_LEFT_CONTROL},
126 {Keys::Escape, GLFW_KEY_ESCAPE},
127 {Keys::Return, GLFW_KEY_ENTER},
128 {Keys::Tab, GLFW_KEY_TAB},
129 {Keys::BackSpace, GLFW_KEY_BACKSPACE},
130 {Keys::Space, GLFW_KEY_SPACE},
131 {Keys::Up, GLFW_KEY_UP},
132 {Keys::Down, GLFW_KEY_DOWN},
133 {Keys::Left, GLFW_KEY_LEFT},
134 {Keys::Right, GLFW_KEY_RIGHT},
135 {Keys::CapsLock, GLFW_KEY_CAPS_LOCK},
136 {Keys::LMB, GLFW_MOUSE_BUTTON_LEFT},
137 {Keys::MMB, GLFW_MOUSE_BUTTON_MIDDLE},
138 {Keys::RMB, GLFW_MOUSE_BUTTON_RIGHT}};
139 return keys;
140}
141
142inline std::unordered_map<int, std::string> get_inv_keys_map() {
143 auto keys = get_keys_map();
144 std::unordered_map<int, std::string> keys_inv;
145 for (auto kv : keys) {
146 keys_inv[kv.second] = kv.first;
147 }
148 keys_inv[GLFW_KEY_RIGHT_SHIFT] = Keys::Shift;
149 keys_inv[GLFW_KEY_RIGHT_CONTROL] = Keys::Control;
150 keys_inv[GLFW_KEY_RIGHT_ALT] = Keys::Alt;
151 return keys_inv;
152}
153
154inline int buttom_name_to_id(const std::string &name) {
155 if (name.size() == 1) {
156 char c = name[0];
157 if (c >= 'a' && c <= 'z') {
158 c = c - ('a' - 'A');
159 return (int)c;
160 }
161 }
162
163 auto keys = get_keys_map();
164
165 if (keys.find(name) != keys.end()) {
166 return keys.at(name);
167 } else {
168 throw std::runtime_error(std::string("unrecognized name: ") + name);
169 }
170}
171
172inline std::string button_id_to_name(int id) {
173 if (id >= 'A' && id <= 'Z') {
174 char c = id + ('a' - 'A');
175 std::string name;
176 name += c;
177 return name;
178 }
179 auto keys = get_inv_keys_map();
180
181 if (keys.find(id) != keys.end()) {
182 return keys.at(id);
183 } else {
184 throw std::runtime_error(std::string("unrecognized id: ") +
185 std::to_string(id));
186 }
187}
188#endif
189
190inline std::vector<char> read_file(const std::string &filename) {
191 std::ifstream file(filename, std::ios::ate | std::ios::binary);
192
193 if (!file.is_open()) {
194 throw std::runtime_error(filename + " failed to open file!");
195 }
196
197 size_t fileSize = (size_t)file.tellg();
198 std::vector<char> buffer(fileSize);
199
200 file.seekg(0);
201 file.read(buffer.data(), fileSize);
202
203 file.close();
204
205 return buffer;
206}
207
208} // namespace taichi::ui
209