Compare commits
1
Commits
7af42b9bad
...
b6a449d8e3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6a449d8e3 |
@@ -16,10 +16,12 @@
|
|||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <GLFW/glfw3native.h>
|
#include <GLFW/glfw3native.h>
|
||||||
#include <vulkan/vulkan_wayland.h>
|
#include <vulkan/vulkan_wayland.h>
|
||||||
#include <cstring>
|
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#define VMA_IMPLEMENTATION
|
#define VMA_IMPLEMENTATION
|
||||||
@@ -28,6 +30,63 @@
|
|||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::vector<VkExtensionProperties> enumerateInstanceExtensions() {
|
||||||
|
uint32_t extensionCount = 0;
|
||||||
|
VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr));
|
||||||
|
std::vector<VkExtensionProperties> extensions(extensionCount);
|
||||||
|
if (extensionCount > 0) {
|
||||||
|
VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()));
|
||||||
|
}
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasInstanceExtension(const std::vector<VkExtensionProperties>& extensions, const char* extensionName) {
|
||||||
|
for (const auto& extension : extensions) {
|
||||||
|
if (std::strcmp(extension.extensionName, extensionName) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyCommonGlfwInitHints() {
|
||||||
|
#if defined(GLFW_WAYLAND_LIBDECOR) && defined(GLFW_WAYLAND_DISABLE_LIBDECOR)
|
||||||
|
glfwInitHint(GLFW_WAYLAND_LIBDECOR, GLFW_WAYLAND_DISABLE_LIBDECOR);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeGlfwForVulkan() {
|
||||||
|
applyCommonGlfwInitHints();
|
||||||
|
if (!glfwInit()) {
|
||||||
|
throw std::runtime_error("Failed to initialize GLFW");
|
||||||
|
}
|
||||||
|
if (!glfwVulkanSupported()) {
|
||||||
|
throw std::runtime_error("GLFW: Vulkan not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(GLFW_PLATFORM_WAYLAND) && defined(GLFW_PLATFORM_X11)
|
||||||
|
const auto availableExtensions = enumerateInstanceExtensions();
|
||||||
|
const bool hasWaylandSurface = hasInstanceExtension(availableExtensions, "VK_KHR_wayland_surface");
|
||||||
|
const bool hasXlibSurface = hasInstanceExtension(availableExtensions, "VK_KHR_xlib_surface");
|
||||||
|
const bool hasXcbSurface = hasInstanceExtension(availableExtensions, "VK_KHR_xcb_surface");
|
||||||
|
|
||||||
|
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND && !hasWaylandSurface && (hasXlibSurface || hasXcbSurface)) {
|
||||||
|
std::cerr << "Warning: Vulkan loader does not expose VK_KHR_wayland_surface on this run. Reinitializing GLFW on X11 backend." << std::endl;
|
||||||
|
glfwTerminate();
|
||||||
|
applyCommonGlfwInitHints();
|
||||||
|
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
||||||
|
if (!glfwInit()) {
|
||||||
|
throw std::runtime_error("Failed to reinitialize GLFW on X11 backend");
|
||||||
|
}
|
||||||
|
if (!glfwVulkanSupported()) {
|
||||||
|
throw std::runtime_error("GLFW: Vulkan not supported after switching to X11 backend");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
thread_local PCommandPool Seele::Vulkan::Graphics::graphicsCommands = nullptr;
|
thread_local PCommandPool Seele::Vulkan::Graphics::graphicsCommands = nullptr;
|
||||||
thread_local PCommandPool Seele::Vulkan::Graphics::computeCommands = nullptr;
|
thread_local PCommandPool Seele::Vulkan::Graphics::computeCommands = nullptr;
|
||||||
thread_local PCommandPool Seele::Vulkan::Graphics::transferCommands = nullptr;
|
thread_local PCommandPool Seele::Vulkan::Graphics::transferCommands = nullptr;
|
||||||
@@ -675,31 +734,46 @@ Array<const char*> Graphics::getRequiredExtensions() {
|
|||||||
message += ": ";
|
message += ": ";
|
||||||
message += glfwError;
|
message += glfwError;
|
||||||
}
|
}
|
||||||
extensions.add(VK_KHR_SURFACE_EXTENSION_NAME);
|
std::cerr << "Warning: " << message << ". Falling back to platform-specific surface extensions." << std::endl;
|
||||||
extensions.add(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
|
|
||||||
std::cerr << "Warning: " << message << ". Falling back to a default set of extensions." << std::endl;
|
extensions.addUnique(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
||||||
|
#if defined(GLFW_PLATFORM_WAYLAND) && defined(GLFW_PLATFORM_X11)
|
||||||
|
const int platform = glfwGetPlatform();
|
||||||
|
if (platform == GLFW_PLATFORM_WAYLAND) {
|
||||||
|
extensions.addUnique("VK_KHR_wayland_surface");
|
||||||
|
} else if (platform == GLFW_PLATFORM_X11) {
|
||||||
|
extensions.addUnique("VK_KHR_xlib_surface");
|
||||||
|
extensions.addUnique("VK_KHR_xcb_surface");
|
||||||
|
} else {
|
||||||
|
extensions.addUnique("VK_KHR_wayland_surface");
|
||||||
|
extensions.addUnique("VK_KHR_xlib_surface");
|
||||||
|
extensions.addUnique("VK_KHR_xcb_surface");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool isWayland = std::getenv("WAYLAND_DISPLAY") != nullptr;
|
||||||
|
if (isWayland) {
|
||||||
|
extensions.addUnique("VK_KHR_wayland_surface");
|
||||||
|
} else {
|
||||||
|
extensions.addUnique("VK_KHR_xlib_surface");
|
||||||
|
extensions.addUnique("VK_KHR_xcb_surface");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
// GLFW successfully reported extensions
|
||||||
|
for (unsigned int i = 0; i < glfwExtensionCount; i++) {
|
||||||
|
extensions.addUnique(glfwExtensions[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < glfwExtensionCount; i++) {
|
|
||||||
extensions.add(glfwExtensions[i]);
|
|
||||||
}
|
|
||||||
#ifdef ENABLE_VALIDATION
|
#ifdef ENABLE_VALIDATION
|
||||||
extensions.add(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
extensions.addUnique(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
#endif
|
#endif
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::initInstance(GraphicsInitializer initInfo) {
|
void Graphics::initInstance(GraphicsInitializer initInfo) {
|
||||||
#if defined(GLFW_WAYLAND_LIBDECOR) && defined(GLFW_WAYLAND_DISABLE_LIBDECOR)
|
initializeGlfwForVulkan();
|
||||||
// Work around libdecor runtime regressions on some Wayland stacks.
|
|
||||||
glfwInitHint(GLFW_WAYLAND_LIBDECOR, GLFW_WAYLAND_DISABLE_LIBDECOR);
|
|
||||||
#endif
|
|
||||||
if (!glfwInit()) {
|
|
||||||
throw std::runtime_error("Failed to initialize GLFW");
|
|
||||||
}
|
|
||||||
if (!glfwVulkanSupported()) {
|
|
||||||
throw std::runtime_error("GLFW: Vulkan not supported");
|
|
||||||
}
|
|
||||||
VkApplicationInfo appInfo = {
|
VkApplicationInfo appInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -712,10 +786,10 @@ void Graphics::initInstance(GraphicsInitializer initInfo) {
|
|||||||
|
|
||||||
Array<const char*> extensions = getRequiredExtensions();
|
Array<const char*> extensions = getRequiredExtensions();
|
||||||
for (uint32 i = 0; i < initInfo.instanceExtensions.size(); ++i) {
|
for (uint32 i = 0; i < initInfo.instanceExtensions.size(); ++i) {
|
||||||
extensions.add(initInfo.instanceExtensions[i]);
|
extensions.addUnique(initInfo.instanceExtensions[i]);
|
||||||
}
|
}
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
extensions.add("VK_KHR_portability_enumeration");
|
extensions.addUnique("VK_KHR_portability_enumeration");
|
||||||
#endif
|
#endif
|
||||||
Array<const char*> layers = initInfo.layers;
|
Array<const char*> layers = initInfo.layers;
|
||||||
VkInstanceCreateInfo info = {
|
VkInstanceCreateInfo info = {
|
||||||
|
|||||||
@@ -3,12 +3,79 @@
|
|||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
|
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||||
|
#define GLFW_EXPOSE_NATIVE_X11
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <vulkan/vulkan_wayland.h>
|
||||||
|
#include <vulkan/vulkan_xlib.h>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
VkResult createSurfaceFromNativeHandles(VkInstance instance, GLFWwindow* handle, VkSurfaceKHR* surface, std::string& reason) {
|
||||||
|
#if defined(GLFW_PLATFORM_WAYLAND)
|
||||||
|
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) {
|
||||||
|
auto createWaylandSurface = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(
|
||||||
|
vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR"));
|
||||||
|
if (createWaylandSurface == nullptr) {
|
||||||
|
reason = "vkCreateWaylandSurfaceKHR is unavailable on the Vulkan instance";
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_display* display = glfwGetWaylandDisplay();
|
||||||
|
wl_surface* waylandSurface = glfwGetWaylandWindow(handle);
|
||||||
|
if (display == nullptr || waylandSurface == nullptr) {
|
||||||
|
reason = "GLFW did not provide valid Wayland native handles";
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkWaylandSurfaceCreateInfoKHR createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.display = display,
|
||||||
|
.surface = waylandSurface,
|
||||||
|
};
|
||||||
|
return createWaylandSurface(instance, &createInfo, nullptr, surface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_PLATFORM_X11)
|
||||||
|
if (glfwGetPlatform() == GLFW_PLATFORM_X11) {
|
||||||
|
auto createXlibSurface = reinterpret_cast<PFN_vkCreateXlibSurfaceKHR>(
|
||||||
|
vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR"));
|
||||||
|
if (createXlibSurface == nullptr) {
|
||||||
|
reason = "vkCreateXlibSurfaceKHR is unavailable on the Vulkan instance";
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Display* display = glfwGetX11Display();
|
||||||
|
::Window x11Window = glfwGetX11Window(handle);
|
||||||
|
if (display == nullptr || x11Window == 0) {
|
||||||
|
reason = "GLFW did not provide valid X11 native handles";
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkXlibSurfaceCreateInfoKHR createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.dpy = display,
|
||||||
|
.window = x11Window,
|
||||||
|
};
|
||||||
|
return createXlibSurface(instance, &createInfo, nullptr, surface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
reason = "Unsupported GLFW platform for manual Vulkan surface creation";
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double currentFrameDelta = 0;
|
double currentFrameDelta = 0;
|
||||||
double Gfx::getCurrentFrameDelta() { return currentFrameDelta; }
|
double Gfx::getCurrentFrameDelta() { return currentFrameDelta; }
|
||||||
@@ -23,41 +90,41 @@ void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier)
|
|||||||
if (key == -1) {
|
if (key == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->keyPress((KeyCode)key, (InputAction)action, (KeyModifier)modifier);
|
window->keyPress(static_cast<Seele::KeyCode>(key), static_cast<InputAction>(action), static_cast<KeyModifier>(modifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) {
|
void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->mouseMove(xpos, ypos);
|
window->mouseMove(xpos, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) {
|
void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->mouseButton((MouseButton)button, (InputAction)action, (KeyModifier)modifier);
|
window->mouseButton(static_cast<MouseButton>(button), static_cast<InputAction>(action), static_cast<KeyModifier>(modifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) {
|
void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->scroll(xoffset, yoffset);
|
window->scroll(xoffset, yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) {
|
void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->fileDrop(count, paths);
|
window->fileDrop(count, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwCloseCallback(GLFWwindow* handle) {
|
void glfwCloseCallback(GLFWwindow* handle) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->close();
|
window->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwFramebufferResizeCallback(GLFWwindow* handle, int width, int height) {
|
void glfwFramebufferResizeCallback(GLFWwindow* handle, int width, int height) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->resize(width, height);
|
window->resize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
Seele::Vulkan::Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
||||||
: graphics(graphics), preferences(createInfo), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) {
|
: graphics(graphics), preferences(createInfo), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) {
|
||||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &contentScaleX, &contentScaleY);
|
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &contentScaleX, &contentScaleY);
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
@@ -90,12 +157,20 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
|||||||
if (surfaceResult != VK_SUCCESS || surface == VK_NULL_HANDLE) {
|
if (surfaceResult != VK_SUCCESS || surface == VK_NULL_HANDLE) {
|
||||||
const char* glfwError = nullptr;
|
const char* glfwError = nullptr;
|
||||||
glfwGetError(&glfwError);
|
glfwGetError(&glfwError);
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "Failed to create Vulkan surface via GLFW (VkResult=" << surfaceResult << ")";
|
std::string nativeReason;
|
||||||
if (glfwError != nullptr) {
|
surfaceResult = createSurfaceFromNativeHandles(instance, handle, &surface, nativeReason);
|
||||||
oss << ": " << glfwError;
|
if (surfaceResult != VK_SUCCESS || surface == VK_NULL_HANDLE) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to create Vulkan surface via GLFW (VkResult=" << surfaceResult << ")";
|
||||||
|
if (glfwError != nullptr) {
|
||||||
|
oss << ": " << glfwError;
|
||||||
|
}
|
||||||
|
if (!nativeReason.empty()) {
|
||||||
|
oss << ". Native fallback failed: " << nativeReason;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
}
|
}
|
||||||
throw std::runtime_error(oss.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
querySurface();
|
querySurface();
|
||||||
@@ -108,17 +183,17 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
|||||||
createSwapChain();
|
createSwapChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
Seele::Vulkan::Window::~Window() {
|
||||||
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
|
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
|
||||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||||
glfwDestroyWindow(static_cast<GLFWwindow*>(windowHandle));
|
glfwDestroyWindow(static_cast<GLFWwindow*>(windowHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::pollInput() { glfwPollEvents(); }
|
void Seele::Vulkan::Window::pollInput() { glfwPollEvents(); }
|
||||||
|
|
||||||
void Window::show() { glfwShowWindow(static_cast<GLFWwindow*>(windowHandle)); }
|
void Seele::Vulkan::Window::show() { glfwShowWindow(static_cast<GLFWwindow*>(windowHandle)); }
|
||||||
|
|
||||||
void Window::beginFrame() {
|
void Seele::Vulkan::Window::beginFrame() {
|
||||||
imageAvailableFences[currentSemaphoreIndex]->reset();
|
imageAvailableFences[currentSemaphoreIndex]->reset();
|
||||||
imageAvailableSemaphores[currentSemaphoreIndex]->resolveSignal();
|
imageAvailableSemaphores[currentSemaphoreIndex]->resolveSignal();
|
||||||
imageAvailableSemaphores[currentSemaphoreIndex]->rotateSemaphore();
|
imageAvailableSemaphores[currentSemaphoreIndex]->rotateSemaphore();
|
||||||
@@ -139,7 +214,7 @@ void Window::beginFrame() {
|
|||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::endFrame() {
|
void Seele::Vulkan::Window::endFrame() {
|
||||||
swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR, Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
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_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_MEMORY_READ_BIT,
|
||||||
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||||
@@ -169,39 +244,39 @@ void Window::endFrame() {
|
|||||||
// graphics->waitDeviceIdle();
|
// graphics->waitDeviceIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::shouldClose() const {
|
bool Seele::Vulkan::Window::shouldClose() const {
|
||||||
return glfwWindowShouldClose((GLFWwindow*)windowHandle);
|
return glfwWindowShouldClose((GLFWwindow*)windowHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gfx::PTexture2D Window::getBackBuffer() const { return PTexture2D(swapChainTextures[currentImageIndex]); }
|
Gfx::PTexture2D Seele::Vulkan::Window::getBackBuffer() const { return PTexture2D(swapChainTextures[currentImageIndex]); }
|
||||||
|
|
||||||
void Window::setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) { keyCallback = callback; }
|
void Seele::Vulkan::Window::setKeyCallback(std::function<void(Seele::KeyCode, InputAction, KeyModifier)> callback) { keyCallback = callback; }
|
||||||
|
|
||||||
void Window::setMouseMoveCallback(std::function<void(double, double)> callback) { mouseMoveCallback = callback; }
|
void Seele::Vulkan::Window::setMouseMoveCallback(std::function<void(double, double)> callback) { mouseMoveCallback = callback; }
|
||||||
|
|
||||||
void Window::setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) { mouseButtonCallback = callback; }
|
void Seele::Vulkan::Window::setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) { mouseButtonCallback = callback; }
|
||||||
|
|
||||||
void Window::setScrollCallback(std::function<void(double, double)> callback) { scrollCallback = callback; }
|
void Seele::Vulkan::Window::setScrollCallback(std::function<void(double, double)> callback) { scrollCallback = callback; }
|
||||||
|
|
||||||
void Window::setFileCallback(std::function<void(int, const char**)> callback) { fileCallback = callback; }
|
void Seele::Vulkan::Window::setFileCallback(std::function<void(int, const char**)> callback) { fileCallback = callback; }
|
||||||
|
|
||||||
void Window::setCloseCallback(std::function<void()> callback) { closeCallback = callback; }
|
void Seele::Vulkan::Window::setCloseCallback(std::function<void()> callback) { closeCallback = callback; }
|
||||||
|
|
||||||
void Window::setResizeCallback(std::function<void(uint32, uint32)> callback) { resizeCallback = callback; }
|
void Seele::Vulkan::Window::setResizeCallback(std::function<void(uint32, uint32)> callback) { resizeCallback = callback; }
|
||||||
|
|
||||||
void Window::keyPress(KeyCode code, InputAction action, KeyModifier modifier) { keyCallback(code, action, modifier); }
|
void Seele::Vulkan::Window::keyPress(Seele::KeyCode code, InputAction action, KeyModifier modifier) { keyCallback(code, action, modifier); }
|
||||||
|
|
||||||
void Window::mouseMove(double x, double y) { mouseMoveCallback(x, y); }
|
void Seele::Vulkan::Window::mouseMove(double x, double y) { mouseMoveCallback(x, y); }
|
||||||
|
|
||||||
void Window::mouseButton(MouseButton button, InputAction action, KeyModifier modifier) { mouseButtonCallback(button, action, modifier); }
|
void Seele::Vulkan::Window::mouseButton(MouseButton button, InputAction action, KeyModifier modifier) { mouseButtonCallback(button, action, modifier); }
|
||||||
|
|
||||||
void Window::scroll(double x, double y) { scrollCallback(x, y); }
|
void Seele::Vulkan::Window::scroll(double x, double y) { scrollCallback(x, y); }
|
||||||
|
|
||||||
void Window::fileDrop(int num, const char** files) { fileCallback(num, files); }
|
void Seele::Vulkan::Window::fileDrop(int num, const char** files) { fileCallback(num, files); }
|
||||||
|
|
||||||
void Window::close() { closeCallback(); }
|
void Seele::Vulkan::Window::close() { closeCallback(); }
|
||||||
|
|
||||||
void Window::resize(int width, int height) {
|
void Seele::Vulkan::Window::resize(int width, int height) {
|
||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
paused = true;
|
paused = true;
|
||||||
return;
|
return;
|
||||||
@@ -218,7 +293,7 @@ void Window::resize(int width, int height) {
|
|||||||
resizeCallback(width, height);
|
resizeCallback(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::querySurface() {
|
void Seele::Vulkan::Window::querySurface() {
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &capabilities);
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &capabilities);
|
||||||
|
|
||||||
uint32 numFormats;
|
uint32 numFormats;
|
||||||
@@ -232,7 +307,7 @@ void Window::querySurface() {
|
|||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, supportedPresentModes.data());
|
vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, supportedPresentModes.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::chooseSwapSurfaceFormat() {
|
void Seele::Vulkan::Window::chooseSwapSurfaceFormat() {
|
||||||
for (const auto& supportedFormat : supportedFormats) {
|
for (const auto& supportedFormat : supportedFormats) {
|
||||||
if (supportedFormat.format == cast(preferences.preferredFormat)) {
|
if (supportedFormat.format == cast(preferences.preferredFormat)) {
|
||||||
format = supportedFormat;
|
format = supportedFormat;
|
||||||
@@ -248,7 +323,7 @@ void Window::chooseSwapSurfaceFormat() {
|
|||||||
format = supportedFormats[0];
|
format = supportedFormats[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::chooseSwapPresentMode() {
|
void Seele::Vulkan::Window::chooseSwapPresentMode() {
|
||||||
for (const auto& supportedPresentMode : supportedPresentModes) {
|
for (const auto& supportedPresentMode : supportedPresentModes) {
|
||||||
if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||||
presentMode = supportedPresentMode;
|
presentMode = supportedPresentMode;
|
||||||
@@ -258,7 +333,7 @@ void Window::chooseSwapPresentMode() {
|
|||||||
presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::chooseSwapExtent() {
|
void Seele::Vulkan::Window::chooseSwapExtent() {
|
||||||
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max()) {
|
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max()) {
|
||||||
extent = capabilities.currentExtent;
|
extent = capabilities.currentExtent;
|
||||||
return;
|
return;
|
||||||
@@ -274,7 +349,7 @@ void Window::chooseSwapExtent() {
|
|||||||
extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::createSwapChain() {
|
void Seele::Vulkan::Window::createSwapChain() {
|
||||||
graphics->waitDeviceIdle();
|
graphics->waitDeviceIdle();
|
||||||
uint32 imageCount = Gfx::numFramesBuffered;
|
uint32 imageCount = Gfx::numFramesBuffered;
|
||||||
VkSwapchainCreateInfoKHR createInfo = {
|
VkSwapchainCreateInfoKHR createInfo = {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "slang-compile.h"
|
#include "slang-compile.h"
|
||||||
#include "Containers/Array.h"
|
#include "Containers/Array.h"
|
||||||
#include "Graphics/Descriptor.h"
|
#include "Graphics/Descriptor.h"
|
||||||
|
#include <filesystem>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <slang.h>
|
#include <slang.h>
|
||||||
@@ -27,9 +28,56 @@ thread_local Slang::ComPtr<slang::IComponentType> specializedComponent;
|
|||||||
thread_local Slang::ComPtr<slang::ISession> session;
|
thread_local Slang::ComPtr<slang::ISession> session;
|
||||||
thread_local Array<std::string> entryPoints;
|
thread_local Array<std::string> entryPoints;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::filesystem::path getExecutableDirectory() {
|
||||||
|
std::error_code error;
|
||||||
|
auto exePath = std::filesystem::read_symlink("/proc/self/exe", error);
|
||||||
|
if (!error) {
|
||||||
|
return exePath.parent_path();
|
||||||
|
}
|
||||||
|
return std::filesystem::current_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::path findExistingDirectory(std::initializer_list<std::filesystem::path> candidates) {
|
||||||
|
for (const auto& candidate : candidates) {
|
||||||
|
std::error_code error;
|
||||||
|
if (std::filesystem::exists(candidate, error) && std::filesystem::is_directory(candidate, error)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void configureDownstreamCompilers(slang::IGlobalSession* session) {
|
||||||
|
const auto executableDirectory = getExecutableDirectory();
|
||||||
|
const auto currentDirectory = std::filesystem::current_path();
|
||||||
|
const auto glslangDirectory = findExistingDirectory({
|
||||||
|
executableDirectory / "Seele",
|
||||||
|
executableDirectory / "vcpkg_installed" / "x64-linux" / "lib",
|
||||||
|
currentDirectory / "Seele",
|
||||||
|
currentDirectory / "vcpkg_installed" / "x64-linux" / "lib",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!glslangDirectory.empty()) {
|
||||||
|
const std::string path = glslangDirectory.string();
|
||||||
|
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_GLSLANG, path.c_str());
|
||||||
|
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_OPT, path.c_str());
|
||||||
|
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_DIS, path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid optional SPIR-V downstream tools that are often unavailable in RenderDoc launch environments.
|
||||||
|
session->setDefaultDownstreamCompiler(SLANG_SOURCE_LANGUAGE_SPIRV, SLANG_PASS_THROUGH_NONE);
|
||||||
|
session->setDownstreamCompilerForTransition(SLANG_SPIRV, SLANG_SPIRV, SLANG_PASS_THROUGH_NONE);
|
||||||
|
session->setDownstreamCompilerForTransition(SLANG_SPIRV, SLANG_SPIRV_ASM, SLANG_PASS_THROUGH_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout) {
|
void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout) {
|
||||||
if (!globalSession) {
|
if (!globalSession) {
|
||||||
slang::createGlobalSession(globalSession.writeRef());
|
SlangGlobalSessionDesc sessionDesc = {};
|
||||||
|
sessionDesc.enableGLSL = true;
|
||||||
|
slang::createGlobalSession(&sessionDesc, globalSession.writeRef());
|
||||||
|
configureDownstreamCompilers(globalSession);
|
||||||
}
|
}
|
||||||
slang::SessionDesc sessionDesc;
|
slang::SessionDesc sessionDesc;
|
||||||
sessionDesc.flags = 0;
|
sessionDesc.flags = 0;
|
||||||
@@ -42,6 +90,30 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
|
|||||||
.intValue0 = info.dumpIntermediate,
|
.intValue0 = info.dumpIntermediate,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = slang::CompilerOptionName::Optimization,
|
||||||
|
.value =
|
||||||
|
{
|
||||||
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
|
.intValue0 = SLANG_OPTIMIZATION_LEVEL_NONE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = slang::CompilerOptionName::SkipSPIRVValidation,
|
||||||
|
.value =
|
||||||
|
{
|
||||||
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
|
.intValue0 = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = slang::CompilerOptionName::SkipDownstreamLinking,
|
||||||
|
.value =
|
||||||
|
{
|
||||||
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
|
.intValue0 = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
sessionDesc.compilerOptionEntries = option.data();
|
sessionDesc.compilerOptionEntries = option.data();
|
||||||
|
|||||||
Reference in New Issue
Block a user