diff --git a/.vscode/launch.json b/.vscode/launch.json index 1b9f2e6..80e644e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,6 +23,17 @@ } ] "preLaunchTask": "Build project", + }, + { + "name": "C/C++: cl.exe build and debug active file", + "type": "cppvsdbg", + "request": "launch", + "program": "${workspaceFolder}\\out\\debug\\demo.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}\\out\\debug", + "environment": [], + "externalConsole": false, } - ] + ] } \ No newline at end of file diff --git a/build/BUILD.gn b/build/BUILD.gn index eb9367d..4700b6b 100644 --- a/build/BUILD.gn +++ b/build/BUILD.gn @@ -173,7 +173,9 @@ config("warnings") { # Disable the following warnings: "/wd4061", # enumerator in switch with a default case not explicitly # handled by a case label. - "/wd4100", # unreferenced format parameter. + "/wd4100", # nonstandard extension used: nameless struct/union. + "/wd4201", # enumerator in switch with a default case not explicitly + # handled by a case label. "/wd4324", # structure was padded due to alignment specifier "/wd4371", # layout of class may have changed from a previous version of # the compiler due to better packing of member @@ -185,6 +187,10 @@ config("warnings") { # switch specified. # TODO: Not sure how I feel about these conversion warnings. + "/Wv:18", # tmp + "/wd4191", # tmp:'type cast': unsafe conversion + "/wd4242", # tmp:conversion from 'int' to 'uint8_t' + "/wd4245", # tmp:conversion from 'int' to 'const unsigned int' "/wd4244", # conversion, possible loss of data. 'int' to 'float' "/wd4267", # conversion, possible loss of data. "/wd4305", # truncation from 'double' to 'float'. @@ -232,6 +238,7 @@ config("warnings") { defines = [ "_CRT_NONSTDC_NO_DEPRECATE", "_SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING", + "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS", ] } else if (is_mac) { cflags = [ diff --git a/src/base/vecmath.h b/src/base/vecmath.h index ce4164a..1658a2e 100644 --- a/src/base/vecmath.h +++ b/src/base/vecmath.h @@ -1247,8 +1247,8 @@ class Matrix4 { T fov_aspect, T width, T height, - T near, - T far) { + T near_, + T far_) { // Calc x and y scale from FOV. T scale = T(2.0) / @@ -1257,8 +1257,8 @@ class Matrix4 { T x_scale = y_scale / (width / height); _M_SET_ROW(0, x_scale / T(2.0), 0, 0, 0); _M_SET_ROW(1, 0, (-y_scale) / T(2.0), 0, 0); - _M_SET_ROW(2, 0, 0, far / (far - near), 1); - _M_SET_ROW(3, 0, 0, -near * far / (far - near), 0); + _M_SET_ROW(2, 0, 0, far_ / (far_ - near_), 1); + _M_SET_ROW(3, 0, 0, -near_ * far_ / (far_ - near_), 0); } void CreateTranslation(const Vector3& t) { diff --git a/src/demo/BUILD.gn b/src/demo/BUILD.gn index c399e49..0927ee8 100644 --- a/src/demo/BUILD.gn +++ b/src/demo/BUILD.gn @@ -18,7 +18,7 @@ executable("demo") { ] deps = [ - "//assets", + # "//assets", "//src/base", "//src/engine", ] diff --git a/src/demo/player.cc b/src/demo/player.cc index 5025bf5..f259836 100644 --- a/src/demo/player.cc +++ b/src/demo/player.cc @@ -2,6 +2,7 @@ #include "base/interpolation.h" #include "base/log.h" +#include "base/vecmath.h" #include "engine/asset/font.h" #include "engine/engine.h" #include "engine/input_event.h" diff --git a/src/engine/BUILD.gn b/src/engine/BUILD.gn index 90c29e2..1a71154 100644 --- a/src/engine/BUILD.gn +++ b/src/engine/BUILD.gn @@ -80,6 +80,23 @@ source_set("engine") { ] } + if (target_os == "win") { + sources += [ + "audio/audio_sink_null.h", + "platform/asset_file_linux.cc", + "platform/platform_win.cc", + "renderer/opengl/renderer_opengl_win.cc", + "renderer/vulkan/renderer_vulkan_win.cc", + "renderer/vulkan/vulkan_context_win.cc", + ] + + libs = [ + # "gdi32.lib", # Graphics + "user32.lib", # Win32 API core functionality. + # "shell32.lib", # Drag and Drop + ] + } + deps = [ "//assets/engine", "//src/base", diff --git a/src/engine/audio/audio_mixer.cc b/src/engine/audio/audio_mixer.cc index ac8c27b..8bc055a 100644 --- a/src/engine/audio/audio_mixer.cc +++ b/src/engine/audio/audio_mixer.cc @@ -11,6 +11,8 @@ #include "engine/audio/audio_sink_oboe.h" #elif defined(__linux__) #include "engine/audio/audio_sink_alsa.h" +#elif defined(_WIN32) +#include "engine/audio/audio_sink_null.h" #endif using namespace base; @@ -23,6 +25,8 @@ AudioMixer::AudioMixer() audio_sink_{std::make_unique(this)} { #elif defined(__linux__) audio_sink_{std::make_unique(this)} { +#elif defined(_WIN32) + audio_sink_{std::make_unique()} { #endif bool res = audio_sink_->Initialize(); CHECK(res) << "Failed to initialize audio sink."; diff --git a/src/engine/audio/audio_sink_null.h b/src/engine/audio/audio_sink_null.h new file mode 100644 index 0000000..d8c2055 --- /dev/null +++ b/src/engine/audio/audio_sink_null.h @@ -0,0 +1,23 @@ +#ifndef ENGINE_AUDIO_AUDIO_SINK_NULL_H +#define ENGINE_AUDIO_AUDIO_SINK_NULL_H + +#include "engine/audio/audio_sink.h" + +namespace eng { + +class AudioSinkNull final : public AudioSink { + public: + AudioSinkNull() = default; + ~AudioSinkNull() final = default; + + bool Initialize() final { return true; } + + void Suspend() final {} + void Resume() final {} + + size_t GetHardwareSampleRate() final { return 0; } +}; + +} // namespace eng + +#endif // ENGINE_AUDIO_AUDIO_SINK_NULL_H diff --git a/src/engine/platform/asset_file.h b/src/engine/platform/asset_file.h index 3f846ac..8f17e6d 100644 --- a/src/engine/platform/asset_file.h +++ b/src/engine/platform/asset_file.h @@ -7,7 +7,7 @@ #if defined(__ANDROID__) #include #include "third_party/minizip/unzip.h" -#elif defined(__linux__) +#else #include "base/file.h" #endif @@ -34,7 +34,7 @@ class AssetFile { #if defined(__ANDROID__) unzFile archive_ = 0; size_t uncompressed_size_ = 0; -#elif defined(__linux) +#else base::ScopedFILE file_; #endif }; diff --git a/src/engine/platform/platform.h b/src/engine/platform/platform.h index 37e1805..b1bf886 100644 --- a/src/engine/platform/platform.h +++ b/src/engine/platform/platform.h @@ -16,6 +16,13 @@ struct ANativeWindow; #include #include +#elif defined(_WIN32) + +// #include +// #define _WIN32_WINNT 0x0601 +// #include +#include + #endif namespace eng { @@ -28,6 +35,8 @@ class Platform { Platform(android_app* app); #elif defined(__linux__) Platform(); +#elif defined(_WIN32) + Platform(HINSTANCE hInstance, int nCmdShow); #endif ~Platform(); @@ -62,6 +71,9 @@ class Platform { #elif defined(__linux__) Display* GetDisplay(); Window GetWindow(); +#elif defined(_WIN32) + HINSTANCE GetInstance(); + HWND GetWindow(); #endif private: @@ -111,6 +123,15 @@ class Platform { XVisualInfo* GetXVisualInfo(Display* display); +#elif defined(_WIN32) + + // Global Variables: + HINSTANCE hInst; // current instance + HWND hWnd; + + // Forward declarations of functions included in this code module: + static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); + #endif Platform(const Platform&) = delete; diff --git a/src/engine/platform/platform_win.cc b/src/engine/platform/platform_win.cc new file mode 100644 index 0000000..00914b0 --- /dev/null +++ b/src/engine/platform/platform_win.cc @@ -0,0 +1,131 @@ +#include "engine/platform/platform.h" + +// #include +// #include +// #include +// #include +// +#include "base/log.h" +// #include "base/vecmath.h" +// #include "engine/input_event.h" +// #include "engine/platform/platform_observer.h" + +using namespace base; + +namespace eng { + +void KaliberMain(Platform* platform); + +Platform::Platform(HINSTANCE hInstance, int nCmdShow) : hInst(hInstance) { + LOG(0) << "Initializing platform."; + + root_path_ = "./"; + data_path_ = "./"; + shared_data_path_ = "./"; + + LOG(0) << "Root path: " << root_path_.c_str(); + LOG(0) << "Data path: " << data_path_.c_str(); + LOG(0) << "Shared data path: " << shared_data_path_.c_str(); + + WNDCLASSEXW wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = + nullptr; // LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT1)); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = nullptr; // MAKEINTRESOURCEW(IDC_WINDOWSPROJECT1); + wcex.lpszClassName = L"szWindowClass"; + wcex.hIconSm = + nullptr; // LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + RegisterClassExW(&wcex); + + hWnd = CreateWindowW(L"szWindowClass", L"kaliber", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, + hInstance, nullptr); + CHECK(hWnd); + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); +} + +Platform::~Platform() { + LOG(0) << "Shutting down platform."; +} + +void Platform::Update() {} + +void Platform::Exit() { + should_exit_ = true; +} + +void Platform::Vibrate(int duration) {} + +void Platform::ShowInterstitialAd() {} + +void Platform::ShareFile(const std::string& file_name) {} + +void Platform::SetKeepScreenOn(bool keep_screen_on) {} + +HINSTANCE Platform::GetInstance() { + return hInst; +} + +HWND Platform::GetWindow() { + return hWnd; +} + +LRESULT CALLBACK Platform::WndProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam) { + // switch (message) + // { + // case WM_COMMAND: + // { + // int wmId = LOWORD(wParam); + // // Parse the menu selections: + // switch (wmId) + // { + // case IDM_ABOUT: + // DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); + // break; + // case IDM_EXIT: + // DestroyWindow(hWnd); + // break; + // default: + // return DefWindowProc(hWnd, message, wParam, lParam); + // } + // } + // break; + // case WM_PAINT: + // { + // PAINTSTRUCT ps; + // HDC hdc = BeginPaint(hWnd, &ps); + // // TODO: Add any drawing code that uses hdc here... + // EndPaint(hWnd, &ps); + // } + // break; + // case WM_DESTROY: + // PostQuitMessage(0); + // break; + // default: + return DefWindowProc(hWnd, message, wParam, lParam); + // } + // return 0; +} + +} // namespace eng + +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) { + eng::Platform platform(hInstance, nCmdShow); + eng::KaliberMain(&platform); + return 0; +} diff --git a/src/engine/renderer/opengl/opengl.h b/src/engine/renderer/opengl/opengl.h index 11ec572..aa135f5 100644 --- a/src/engine/renderer/opengl/opengl.h +++ b/src/engine/renderer/opengl/opengl.h @@ -17,6 +17,16 @@ #define GL_ETC1_RGB8_OES 0x8D64 #endif +#elif defined(_WIN32) +#define GLEW_STATIC +#include "third_party/glew/glew.h" +#include "third_party/glew/wglew.h" + +// Define the missing format for the etc1 +#ifndef GL_ETC1_RGB8_OES +#define GL_ETC1_RGB8_OES 0x8D64 +#endif + #endif #endif // ENGINE_RENDERER_OPENGL_OPENGL_H diff --git a/src/engine/renderer/opengl/renderer_opengl_win.cc b/src/engine/renderer/opengl/renderer_opengl_win.cc new file mode 100644 index 0000000..155854d --- /dev/null +++ b/src/engine/renderer/opengl/renderer_opengl_win.cc @@ -0,0 +1,27 @@ +#include "engine/renderer/opengl/renderer_opengl.h" + +#include "base/log.h" +#include "engine/platform/platform.h" + +namespace eng { + +bool RendererOpenGL::Initialize(Platform* platform) { + LOG(0) << "Initializing renderer."; + + return InitCommon(); +} + +void RendererOpenGL::OnDestroy() {} + +void RendererOpenGL::Shutdown() { + LOG(0) << "Shutting down renderer."; + is_initialized_ = false; +} + +void RendererOpenGL::Present() { + active_shader_id_ = 0; + active_texture_id_ = 0; + fps_++; +} + +} // namespace eng diff --git a/src/engine/renderer/vulkan/renderer_vulkan_win.cc b/src/engine/renderer/vulkan/renderer_vulkan_win.cc new file mode 100644 index 0000000..cb0d2ad --- /dev/null +++ b/src/engine/renderer/vulkan/renderer_vulkan_win.cc @@ -0,0 +1,29 @@ +#include "engine/renderer/vulkan/renderer_vulkan.h" + +#include "base/log.h" +#include "engine/platform/platform.h" + +namespace eng { + +bool RendererVulkan::Initialize(Platform* platform) { + LOG(0) << "Initializing renderer."; + + // XWindowAttributes xwa; + // XGetWindowAttributes(platform->GetInstance(), platform->GetWindow(), &xwa); + RECT rect; + GetClientRect(platform->GetWindow(), &rect); + + if (!context_.Initialize()) { + LOG(0) << "Failed to initialize Vulkan context."; + return false; + } + if (!context_.CreateSurface(platform->GetInstance(), platform->GetWindow(), + rect.right, rect.bottom)) { + LOG(0) << "Vulkan context failed to create window."; + return false; + } + + return InitializeInternal(); +} + +} // namespace eng diff --git a/src/engine/renderer/vulkan/vulkan_context.cc b/src/engine/renderer/vulkan/vulkan_context.cc index 02f96ef..612e4db 100644 --- a/src/engine/renderer/vulkan/vulkan_context.cc +++ b/src/engine/renderer/vulkan/vulkan_context.cc @@ -703,7 +703,7 @@ bool VulkanContext::InitializeQueues(VkSurfaceKHR surface) { #if defined(__ANDROID__) VkFormat desired_format = VK_FORMAT_R8G8B8A8_UNORM; -#elif defined(__linux__) +#elif defined(__linux__) || defined(_WIN32) VkFormat desired_format = VK_FORMAT_B8G8R8A8_UNORM; #endif diff --git a/src/engine/renderer/vulkan/vulkan_context.h b/src/engine/renderer/vulkan/vulkan_context.h index 5537483..481ba6b 100644 --- a/src/engine/renderer/vulkan/vulkan_context.h +++ b/src/engine/renderer/vulkan/vulkan_context.h @@ -11,6 +11,10 @@ struct ANativeWindow; #endif +// #if defined(_WIN32) +// #include +// #endif + namespace eng { // Adapted from godot engin. @@ -27,6 +31,8 @@ class VulkanContext { bool CreateWindow(ANativeWindow* window, int width, int height); #elif defined(__linux__) bool CreateWindow(Display* display, ::Window window, int width, int height); +#elif defined(_WIN32) + bool CreateSurface(HINSTANCE hInstance, HWND hWnd, int width, int height); #endif void ResizeWindow(int width, int height); diff --git a/src/engine/renderer/vulkan/vulkan_context_win.cc b/src/engine/renderer/vulkan/vulkan_context_win.cc new file mode 100644 index 0000000..c1a3d40 --- /dev/null +++ b/src/engine/renderer/vulkan/vulkan_context_win.cc @@ -0,0 +1,47 @@ +#include "engine/renderer/vulkan/vulkan_context.h" + +// #if defined(_WIN32) +// #include +// #endif + +#include "base/log.h" + +namespace eng { + +const char* VulkanContext::GetPlatformSurfaceExtension() const { + return VK_KHR_WIN32_SURFACE_EXTENSION_NAME; +} + +bool VulkanContext::CreateSurface(HINSTANCE hInstance, + HWND hWnd, + int width, + int height) { + VkWin32SurfaceCreateInfoKHR create_info; + create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.hinstance = hInstance; + create_info.hwnd = hWnd; + + VkSurfaceKHR surface; + VkResult err = + vkCreateWin32SurfaceKHR(instance_, &create_info, nullptr, &surface); + if (err != VK_SUCCESS) { + LOG(0) << "vkCreateWin32SurfaceKHR failed with error " + << std::to_string(err); + return false; + } + + if (!queues_initialized_ && !InitializeQueues(surface)) + return false; + + window_.surface = surface; + window_.width = width; + window_.height = height; + if (!UpdateSwapChain(&window_)) + return false; + + return true; +} + +} // namespace eng diff --git a/src/third_party/BUILD.gn b/src/third_party/BUILD.gn index 4ad2dcf..489f5a8 100644 --- a/src/third_party/BUILD.gn +++ b/src/third_party/BUILD.gn @@ -7,6 +7,10 @@ config("third_party_config") { if (target_os == "linux") { defines = [ "VK_USE_PLATFORM_XLIB_KHR" ] } + + if (target_os == "win") { + defines = [ "VK_USE_PLATFORM_WIN32_KHR" ] + } } source_set("third_party") { @@ -53,7 +57,8 @@ source_set("third_party") { "glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp", "glslang/glslang/MachineIndependent/propagateNoContraction.cpp", "glslang/glslang/MachineIndependent/reflection.cpp", - "glslang/glslang/OSDependent/Unix/ossource.cpp", + # "glslang/glslang/OSDependent/Unix/ossource.cpp", + "glslang/glslang/OSDependent/Windows/ossource.cpp", "jsoncpp/json.h", "jsoncpp/jsoncpp.cpp", "minimp3/minimp3.h", @@ -84,6 +89,16 @@ source_set("third_party") { ] } + if (target_os == "win") { + sources += [ + "glew/glew.c", + "glew/glew.h", + "glew/wglew.h", + ] + + libs = [ "opengl32.lib" ] + } + configs -= [ "//build:warnings" ] deps = [] diff --git a/src/third_party/glslang/glslang/MachineIndependent/Constant.cpp b/src/third_party/glslang/glslang/MachineIndependent/Constant.cpp index 5fc61db..a4d80bd 100644 --- a/src/third_party/glslang/glslang/MachineIndependent/Constant.cpp +++ b/src/third_party/glslang/glslang/MachineIndependent/Constant.cpp @@ -213,8 +213,8 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right case EbtInt64: if (rightUnionArray[i] == 0ll) newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll); - else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)-0x8000000000000000ll) - newConstArray[i].setI64Const((long long)-0x8000000000000000ll); + else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)0x8000000000000000ll) + newConstArray[i].setI64Const((long long)0x8000000000000000ll); else newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const()); break;