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 | |
45 | namespace 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 |
55 | inline 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 | |
99 | struct 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 | |
121 | inline 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 | |
142 | inline 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 | |
154 | inline 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 | |
172 | inline 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 | |
190 | inline 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 | |