|
3 | 3 | // |
4 | 4 |
|
5 | 5 | #include <Launch/GameViewport.h> |
| 6 | +#include <Runtime/Engine.h> |
| 7 | + |
| 8 | +namespace Launch::Internal { |
| 9 | + static void* GetGlfwPlatformWindow(GLFWwindow* inWindow) |
| 10 | + { |
| 11 | +#if PLATFORM_WINDOWS |
| 12 | + return glfwGetWin32Window(inWindow); |
| 13 | +#elif PLATFORM_MACOS |
| 14 | + return glfwGetCocoaView(inWindow); |
| 15 | +#else |
| 16 | + Unimplement(); |
| 17 | + return nullptr; |
| 18 | +#endif |
| 19 | + } |
| 20 | +} |
6 | 21 |
|
7 | 22 | namespace Launch { |
8 | | - GameViewport::GameViewport() |
| 23 | + GameViewport::GameViewport(const GameViewportDesc& inDesc) |
| 24 | + : renderModule(Runtime::EngineHolder::Get().GetRenderModule()) |
| 25 | + , client(*this) |
9 | 26 | { |
10 | | - // TODO |
| 27 | + glfwInit(); |
| 28 | + window = glfwCreateWindow(static_cast<int>(inDesc.width), static_cast<int>(inDesc.height), inDesc.title.c_str(), nullptr, nullptr); |
| 29 | + |
| 30 | + device = renderModule.GetDevice(); |
| 31 | + imageReadySemaphore = device->CreateSemaphore(); |
| 32 | + renderFinishedSemaphore = device->CreateSemaphore(); |
| 33 | + |
| 34 | + surface = device->CreateSurface(RHI::SurfaceCreateInfo(Internal::GetGlfwPlatformWindow(window))); |
| 35 | + RecreateSwapChain(inDesc.width, inDesc.height); |
11 | 36 | } |
12 | 37 |
|
13 | 38 | GameViewport::~GameViewport() |
14 | 39 | { |
15 | | - // TODO |
| 40 | + WaitDeviceIdle(); |
| 41 | + glfwDestroyWindow(window); |
| 42 | + glfwTerminate(); |
16 | 43 | } |
17 | 44 |
|
18 | 45 | Runtime::Client& GameViewport::GetClient() |
19 | 46 | { |
20 | | - // TODO |
21 | | - return *static_cast<Runtime::Client*>(nullptr); |
| 47 | + return client; |
22 | 48 | } |
23 | 49 |
|
24 | 50 | Runtime::PresentInfo GameViewport::GetNextPresentInfo() |
25 | 51 | { |
26 | | - // TODO |
27 | | - return Runtime::PresentInfo(); |
| 52 | + const auto backTextureIndex = swapChain->AcquireBackTexture(imageReadySemaphore.Get()); |
| 53 | + |
| 54 | + Runtime::PresentInfo result; |
| 55 | + result.backTexture = swapChain->GetTexture(backTextureIndex); |
| 56 | + result.imageReadySemaphore = imageReadySemaphore.Get(); |
| 57 | + result.renderFinishedSemaphore = renderFinishedSemaphore.Get(); |
| 58 | + return result; |
| 59 | + } |
| 60 | + |
| 61 | + uint32_t GameViewport::GetWidth() const |
| 62 | + { |
| 63 | + int width; |
| 64 | + glfwGetWindowSize(window, &width, nullptr); |
| 65 | + return static_cast<uint32_t>(width); |
| 66 | + } |
| 67 | + |
| 68 | + uint32_t GameViewport::GetHeight() const |
| 69 | + { |
| 70 | + int height; |
| 71 | + glfwGetWindowSize(window, nullptr, &height); |
| 72 | + return static_cast<uint32_t>(height); |
28 | 73 | } |
29 | 74 |
|
30 | | - size_t GameViewport::GetWidth() const |
| 75 | + void GameViewport::Resize(uint32_t inWidth, uint32_t inHeight) |
31 | 76 | { |
32 | | - // TODO |
33 | | - return 0; |
| 77 | + glfwSetWindowSize(window, static_cast<int>(inWidth), static_cast<int>(inHeight)); |
| 78 | + RecreateSwapChain(inWidth, inHeight); |
34 | 79 | } |
35 | 80 |
|
36 | | - size_t GameViewport::GetHeight() const |
| 81 | + bool GameViewport::ShouldClose() const |
37 | 82 | { |
38 | | - // TODO |
39 | | - return 0; |
| 83 | + return static_cast<bool>(glfwWindowShouldClose(window)); |
| 84 | + } |
| 85 | + |
| 86 | + void GameViewport::PollEvents() const // NOLINT |
| 87 | + { |
| 88 | + glfwPollEvents(); |
| 89 | + } |
| 90 | + |
| 91 | + void GameViewport::RecreateSwapChain(uint32_t inWidth, uint32_t inHeight) |
| 92 | + { |
| 93 | + static std::vector<RHI::PixelFormat> formatQualifiers = { |
| 94 | + RHI::PixelFormat::rgba8Unorm, |
| 95 | + RHI::PixelFormat::bgra8Unorm |
| 96 | + }; |
| 97 | + |
| 98 | + WaitDeviceIdle(); |
| 99 | + if (swapChain.Valid()) { |
| 100 | + swapChain.Reset(); |
| 101 | + } |
| 102 | + |
| 103 | + std::optional<RHI::PixelFormat> pixelFormat = {}; |
| 104 | + for (const auto format : formatQualifiers) { |
| 105 | + if (device->CheckSwapChainFormatSupport(surface.Get(), format)) { |
| 106 | + pixelFormat = format; |
| 107 | + break; |
| 108 | + } |
| 109 | + } |
| 110 | + Assert(pixelFormat.has_value()); |
| 111 | + |
| 112 | + swapChain = device->CreateSwapChain( |
| 113 | + RHI::SwapChainCreateInfo() |
| 114 | + .SetPresentQueue(device->GetQueue(RHI::QueueType::graphics, 0)) |
| 115 | + .SetSurface(surface.Get()) |
| 116 | + .SetTextureNum(2) |
| 117 | + .SetFormat(pixelFormat.value()) |
| 118 | + .SetWidth(inWidth) |
| 119 | + .SetHeight(inHeight) |
| 120 | + .SetPresentMode(RHI::PresentMode::immediately)); |
| 121 | + } |
| 122 | + |
| 123 | + void GameViewport::WaitDeviceIdle() const |
| 124 | + { |
| 125 | + renderModule.GetRenderThread().Flush(); |
| 126 | + |
| 127 | + const Common::UniquePtr<RHI::Fence> fence = device->CreateFence(false); |
| 128 | + device->GetQueue(RHI::QueueType::graphics, 0)->Flush(fence.Get()); |
| 129 | + fence->Wait(); |
40 | 130 | } |
41 | 131 | } |
0 commit comments