Files
Seele/src/Engine/Graphics/Vulkan/Window.cpp
T

314 lines
13 KiB
C++
Raw Normal View History

2023-11-16 22:58:47 +01:00
#include "Window.h"
#include "Command.h"
2024-06-09 12:20:04 +02:00
#include "Enums.h"
#include "Graphics.h"
#include "Resources.h"
2023-11-16 22:58:47 +01:00
#include <GLFW/glfw3.h>
using namespace Seele;
using namespace Seele::Vulkan;
double currentFrameDelta = 0;
2024-06-09 12:20:04 +02:00
double Gfx::getCurrentFrameDelta() { return currentFrameDelta; }
2023-11-16 22:58:47 +01:00
2024-08-13 22:44:04 +02:00
double currentFrameTime = 0;
double Gfx::getCurrentFrameTime() { return currentFrameTime; }
2024-10-07 20:14:00 +02:00
uint32 currentFrameIndex = std::numeric_limits<uint32>::max();
2024-06-09 12:20:04 +02:00
uint32 Gfx::getCurrentFrameIndex() { return currentFrameIndex; }
2024-05-15 15:27:13 +02:00
2024-06-09 12:20:04 +02:00
void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier) {
if (key == -1) {
2023-12-03 00:29:02 +01:00
return;
}
2023-11-16 22:58:47 +01:00
Window* window = (Window*)glfwGetWindowUserPointer(handle);
2023-11-18 11:04:30 +01:00
window->keyPress((KeyCode)key, (InputAction)action, (KeyModifier)modifier);
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) {
2023-11-16 22:58:47 +01:00
Window* window = (Window*)glfwGetWindowUserPointer(handle);
2023-11-18 11:04:30 +01:00
window->mouseMove(xpos, ypos);
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) {
2023-11-16 22:58:47 +01:00
Window* window = (Window*)glfwGetWindowUserPointer(handle);
2023-11-18 11:04:30 +01:00
window->mouseButton((MouseButton)button, (InputAction)action, (KeyModifier)modifier);
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) {
2023-11-16 22:58:47 +01:00
Window* window = (Window*)glfwGetWindowUserPointer(handle);
2023-11-18 11:04:30 +01:00
window->scroll(xoffset, yoffset);
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) {
2023-11-16 22:58:47 +01:00
Window* window = (Window*)glfwGetWindowUserPointer(handle);
2023-11-18 11:04:30 +01:00
window->fileDrop(count, paths);
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
void glfwCloseCallback(GLFWwindow* handle) {
2023-11-16 22:58:47 +01:00
Window* window = (Window*)glfwGetWindowUserPointer(handle);
2023-11-18 11:04:30 +01:00
window->close();
2023-11-16 22:58:47 +01:00
}
2024-01-24 23:10:33 +01:00
2024-06-09 12:20:04 +02:00
void glfwFramebufferResizeCallback(GLFWwindow* handle, int width, int height) {
2023-11-17 22:31:26 +01:00
Window* window = (Window*)glfwGetWindowUserPointer(handle);
window->resize(width, height);
}
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
: graphics(graphics), preferences(createInfo), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) {
float xscale, yscale;
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xscale, &yscale);
2023-11-16 22:58:47 +01:00
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
2024-06-09 12:20:04 +02:00
GLFWwindow* handle = glfwCreateWindow(createInfo.width / xscale, createInfo.height / yscale, createInfo.title, nullptr, nullptr);
2023-11-16 22:58:47 +01:00
windowHandle = handle;
glfwSetWindowUserPointer(handle, this);
glfwSetKeyCallback(handle, &glfwKeyCallback);
glfwSetCursorPosCallback(handle, &glfwMouseMoveCallback);
glfwSetMouseButtonCallback(handle, &glfwMouseButtonCallback);
glfwSetScrollCallback(handle, &glfwScrollCallback);
glfwSetDropCallback(handle, &glfwFileCallback);
glfwSetWindowCloseCallback(handle, &glfwCloseCallback);
2024-01-24 23:10:33 +01:00
glfwSetFramebufferSizeCallback(handle, &glfwFramebufferResizeCallback);
2024-06-09 12:20:04 +02:00
// glfwSetWindowSizeCallback(handle, &glfwResizeCallback);
2023-11-16 22:58:47 +01:00
glfwCreateWindowSurface(instance, handle, nullptr, &surface);
2024-06-09 12:20:04 +02:00
2023-11-17 22:31:26 +01:00
querySurface();
2023-11-16 22:58:47 +01:00
chooseSwapSurfaceFormat();
framebufferFormat = cast(format.format);
chooseSwapPresentMode();
chooseSwapExtent();
framebufferWidth = extent.width;
framebufferHeight = extent.height;
createSwapChain();
}
2024-06-09 12:20:04 +02:00
Window::~Window() {
2023-11-16 22:58:47 +01:00
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
vkDestroySurfaceKHR(instance, surface, nullptr);
2024-06-09 12:20:04 +02:00
glfwDestroyWindow(static_cast<GLFWwindow*>(windowHandle));
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
void Window::pollInput() { glfwPollEvents(); }
2023-12-28 21:42:18 +01:00
2024-06-09 12:20:04 +02:00
void Window::beginFrame() {
2024-01-24 23:10:33 +01:00
imageAvailableFences[currentSemaphoreIndex]->reset();
2024-07-05 12:02:46 +02:00
VK_CHECK(vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits<uint64>::max(),
imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(),
imageAvailableFences[currentSemaphoreIndex]->getHandle(), &currentImageIndex));
imageAvailableFences[currentSemaphoreIndex]->submit();
2024-06-09 12:20:04 +02:00
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
imageAvailableSemaphores[currentSemaphoreIndex]);
2024-08-13 22:44:04 +02:00
static double start = glfwGetTime();
double end = glfwGetTime();
currentFrameDelta = end - start;
currentFrameTime += currentFrameDelta;
start = end;
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
void Window::endFrame() {
swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR, Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
2023-11-16 22:58:47 +01:00
graphics->getGraphicsCommands()->submitCommands(renderingDoneSemaphores[currentSemaphoreIndex]);
VkSemaphore renderDoneHandle = renderingDoneSemaphores[currentSemaphoreIndex]->getHandle();
VkPresentInfoKHR presentInfo = {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pNext = nullptr,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &renderDoneHandle,
.swapchainCount = 1,
.pSwapchains = &swapchain,
.pImageIndices = &currentImageIndex,
.pResults = nullptr,
};
VkResult r = vkQueuePresentKHR(graphics->getGraphicsCommands()->getQueue()->getHandle(), &presentInfo);
2024-06-09 12:20:04 +02:00
if (r == VK_SUCCESS) {
} else if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR) {
2023-11-16 22:58:47 +01:00
createSwapChain();
2024-06-09 12:20:04 +02:00
} else {
2023-11-16 22:58:47 +01:00
VK_CHECK(r);
}
currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered;
2024-05-15 15:27:13 +02:00
currentFrameIndex = currentSemaphoreIndex;
2024-06-09 12:20:04 +02:00
// graphics->waitDeviceIdle();
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
void Window::onWindowCloseEvent() {}
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
Gfx::PTexture2D Window::getBackBuffer() const { return PTexture2D(swapChainTextures[currentImageIndex]); }
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
void Window::setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) { keyCallback = callback; }
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
void Window::setMouseMoveCallback(std::function<void(double, double)> callback) { mouseMoveCallback = callback; }
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
void Window::setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) { mouseButtonCallback = callback; }
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
void Window::setScrollCallback(std::function<void(double, double)> callback) { scrollCallback = callback; }
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
void Window::setFileCallback(std::function<void(int, const char**)> callback) { fileCallback = callback; }
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
void Window::setCloseCallback(std::function<void()> callback) { closeCallback = callback; }
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
void Window::setResizeCallback(std::function<void(uint32, uint32)> callback) { resizeCallback = callback; }
2023-11-18 11:04:30 +01:00
2024-06-09 12:20:04 +02:00
void Window::keyPress(KeyCode code, InputAction action, KeyModifier modifier) { keyCallback(code, action, modifier); }
2023-11-18 11:04:30 +01:00
2024-06-09 12:20:04 +02:00
void Window::mouseMove(double x, double y) { mouseMoveCallback(x, y); }
2023-11-18 11:04:30 +01:00
2024-06-09 12:20:04 +02:00
void Window::mouseButton(MouseButton button, InputAction action, KeyModifier modifier) { mouseButtonCallback(button, action, modifier); }
2023-11-18 11:04:30 +01:00
2024-06-09 12:20:04 +02:00
void Window::scroll(double x, double y) { scrollCallback(x, y); }
2023-11-18 11:04:30 +01:00
2024-06-09 12:20:04 +02:00
void Window::fileDrop(int num, const char** files) { fileCallback(num, files); }
2023-11-18 11:04:30 +01:00
2024-06-09 12:20:04 +02:00
void Window::close() { closeCallback(); }
2023-11-18 11:04:30 +01:00
2024-06-09 12:20:04 +02:00
void Window::resize(int width, int height) {
if (width == 0 || height == 0) {
2023-12-28 21:42:18 +01:00
paused = true;
return;
}
paused = false;
2023-11-17 22:31:26 +01:00
querySurface();
chooseSwapSurfaceFormat();
framebufferFormat = cast(format.format);
chooseSwapPresentMode();
chooseSwapExtent();
framebufferWidth = extent.width;
framebufferHeight = extent.height;
createSwapChain();
2023-11-18 11:04:30 +01:00
resizeCallback(width, height);
2023-11-17 22:31:26 +01:00
}
2024-06-09 12:20:04 +02:00
void Window::querySurface() {
2023-11-17 22:31:26 +01:00
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &capabilities);
uint32 numFormats;
vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, nullptr);
supportedFormats.resize(numFormats);
vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, supportedFormats.data());
uint32 numPresentModes;
vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, nullptr);
supportedPresentModes.resize(numFormats);
vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, supportedPresentModes.data());
}
2024-06-09 12:20:04 +02:00
void Window::chooseSwapSurfaceFormat() {
for (const auto& supportedFormat : supportedFormats) {
if (supportedFormat.format == cast(preferences.preferredFormat)) {
2023-11-16 22:58:47 +01:00
format = supportedFormat;
return;
}
}
2024-06-09 12:20:04 +02:00
for (const auto& supportedFormat : supportedFormats) {
if (supportedFormat.format == VK_FORMAT_R8G8B8A8_SRGB && supportedFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
2023-11-16 22:58:47 +01:00
format = supportedFormat;
return;
}
}
format = supportedFormats[0];
}
2024-06-09 12:20:04 +02:00
void Window::chooseSwapPresentMode() {
for (const auto& supportedPresentMode : supportedPresentModes) {
if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
2023-11-16 22:58:47 +01:00
presentMode = supportedPresentMode;
return;
}
2024-05-23 14:58:14 +02:00
}
2023-11-16 22:58:47 +01:00
presentMode = VK_PRESENT_MODE_FIFO_KHR;
}
2024-06-09 12:20:04 +02:00
void Window::chooseSwapExtent() {
2023-11-16 22:58:47 +01:00
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max()) {
extent = capabilities.currentExtent;
return;
}
int width, height;
glfwGetFramebufferSize(static_cast<GLFWwindow*>(windowHandle), &width, &height);
extent = {
static_cast<uint32>(width),
static_cast<uint32>(height),
};
extent.width = std::clamp(extent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
}
2024-06-09 12:20:04 +02:00
void Window::createSwapChain() {
2023-11-16 22:58:47 +01:00
uint32 imageCount = Gfx::numFramesBuffered;
VkSwapchainCreateInfoKHR createInfo = {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.pNext = nullptr,
.surface = surface,
.minImageCount = Gfx::numFramesBuffered,
.imageFormat = format.format,
.imageColorSpace = format.colorSpace,
.imageExtent = extent,
.imageArrayLayers = 1,
2023-12-10 22:27:59 +01:00
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
2023-11-16 22:58:47 +01:00
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
.preTransform = capabilities.currentTransform,
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
.presentMode = presentMode,
.clipped = VK_TRUE,
.oldSwapchain = swapchain,
};
VK_CHECK(vkCreateSwapchainKHR(graphics->getDevice(), &createInfo, nullptr, &swapchain));
2023-11-17 18:46:37 +01:00
VK_CHECK(vkGetSwapchainImagesKHR(graphics->getDevice(), swapchain, &imageCount, swapChainImages.data()));
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
for (uint32 i = 0; i < imageCount; ++i) {
swapChainTextures[i] = new Texture2D(graphics,
TextureCreateInfo{
.format = cast(format.format),
.width = extent.width,
.height = extent.height,
.depth = 1,
.layers = 1,
.elements = 1,
.samples = 1,
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_TRANSFER_DST_BIT,
},
swapChainImages[i]);
if (imageAvailableFences[i] != nullptr) {
2024-01-24 23:10:33 +01:00
imageAvailableFences[i]->wait(100000);
imageAvailableFences[i]->reset();
}
imageAvailableFences[i] = new Fence(graphics);
2023-11-16 22:58:47 +01:00
imageAvailableSemaphores[i] = new Semaphore(graphics);
renderingDoneSemaphores[i] = new Semaphore(graphics);
}
}
2024-06-09 12:20:04 +02:00
Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo) : Gfx::Viewport(owner, viewportInfo) {
2023-11-16 22:58:47 +01:00
handle.width = static_cast<float>(sizeX);
handle.height = static_cast<float>(sizeY);
handle.x = static_cast<float>(offsetX);
handle.y = static_cast<float>(offsetY) + handle.height;
handle.height = -handle.height;
2024-06-09 12:20:04 +02:00
handle.minDepth = 1.f;
handle.maxDepth = 0.f;
2023-11-16 22:58:47 +01:00
}
2024-06-09 12:20:04 +02:00
Viewport::~Viewport() {}
2023-11-16 22:58:47 +01:00
2024-06-09 12:20:04 +02:00
void Viewport::resize(uint32 newX, uint32 newY) {
2023-11-16 22:58:47 +01:00
sizeX = newX;
sizeY = newY;
handle.width = static_cast<float>(sizeX);
handle.y = static_cast<float>(sizeY + offsetX);
handle.height = -static_cast<float>(sizeY);
}
2024-06-09 12:20:04 +02:00
void Viewport::move(uint32 newOffsetX, uint32 newOffsetY) {
2023-11-16 22:58:47 +01:00
offsetX = newOffsetX;
offsetY = newOffsetY;
handle.x = static_cast<float>(offsetX);
handle.y = static_cast<float>(offsetY + sizeY);
}