Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7af42b9bad | ||
|
|
ace1554020 | ||
|
|
87390db80d |
+10
-19
@@ -59,7 +59,12 @@ target_include_directories(Engine PRIVATE src/Engine)
|
|||||||
target_link_libraries(Engine PUBLIC Vulkan::Vulkan)
|
target_link_libraries(Engine PUBLIC Vulkan::Vulkan)
|
||||||
target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator)
|
target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator)
|
||||||
if(NOT APPLE)
|
if(NOT APPLE)
|
||||||
target_link_libraries(Engine PUBLIC slang::slang-glslang)
|
# slang-glslang is a MODULE library (plugin) - copy it instead of linking
|
||||||
|
add_custom_command(TARGET Engine POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
$<TARGET_FILE:slang::slang-glslang>
|
||||||
|
$<TARGET_FILE_DIR:Engine>
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(Engine PUBLIC EnTT::EnTT)
|
target_link_libraries(Engine PUBLIC EnTT::EnTT)
|
||||||
target_link_libraries(Engine PUBLIC glfw)
|
target_link_libraries(Engine PUBLIC glfw)
|
||||||
@@ -121,31 +126,17 @@ if(APPLE)
|
|||||||
target_compile_options(Engine PUBLIC -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
|
target_compile_options(Engine PUBLIC -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
|
||||||
target_compile_options(Editor PUBLIC -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
|
target_compile_options(Editor PUBLIC -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
|
||||||
endif()
|
endif()
|
||||||
target_compile_options(Engine PUBLIC "$<$<CONFIG:DEBUG>:-DENABLE_VALIDATION>")
|
|
||||||
target_compile_options(Engine PUBLIC "$<$<CONFIG:DEBUG>:-DSEELE_DEBUG>")
|
|
||||||
|
|
||||||
add_subdirectory(src/)
|
add_subdirectory(src/)
|
||||||
#add_subdirectory(tests/)
|
#add_subdirectory(tests/)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_custom_target(dll_copy ALL
|
add_custom_command(TARGET Engine POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:Engine> $<TARGET_FILE_DIR:Editor>
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:Engine> $<TARGET_FILE_DIR:Editor>)
|
||||||
COMMAND_EXPAND_LISTS
|
|
||||||
DEPENDS Editor)
|
|
||||||
elseif(APPLE)
|
|
||||||
add_custom_target(dll_copy ALL
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E true
|
|
||||||
COMMAND_EXPAND_LISTS
|
|
||||||
DEPENDS Editor)
|
|
||||||
else()
|
|
||||||
add_custom_target(dll_copy ALL
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E true)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target(SeeleEngine ALL
|
add_custom_command(TARGET Engine POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res $<TARGET_FILE_DIR:Engine>
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res $<TARGET_FILE_DIR:Engine>)
|
||||||
COMMAND_EXPAND_LISTS
|
|
||||||
DEPENDS Editor dll_copy)
|
|
||||||
|
|
||||||
install(
|
install(
|
||||||
TARGETS
|
TARGETS
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
(?<enum>[A-Z_]*) = [0-9]*,
|
|
||||||
case SE_${enum}:\nreturn VK_${enum};
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Hint files help the Visual Studio IDE interpret Visual C++ identifiers
|
|
||||||
// such as names of functions and macros.
|
|
||||||
// For more information see https://go.microsoft.com/fwlink/?linkid=865984
|
|
||||||
#define DECLARE_REF(x)
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
#include "RenderTarget.h"
|
#include "RenderTarget.h"
|
||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
|
#define ENABLE_VALIDATION
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
|
#include <vulkan/vulkan_wayland.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
@@ -142,9 +144,7 @@ Graphics::~Graphics() {
|
|||||||
|
|
||||||
void Graphics::init(GraphicsInitializer initInfo) {
|
void Graphics::init(GraphicsInitializer initInfo) {
|
||||||
initInstance(initInfo);
|
initInstance(initInfo);
|
||||||
#ifdef ENABLE_VALIDATION
|
|
||||||
setupDebugCallback();
|
setupDebugCallback();
|
||||||
#endif
|
|
||||||
pickPhysicalDevice();
|
pickPhysicalDevice();
|
||||||
createDevice(initInfo);
|
createDevice(initInfo);
|
||||||
VmaAllocatorCreateInfo createInfo = {
|
VmaAllocatorCreateInfo createInfo = {
|
||||||
@@ -667,6 +667,19 @@ Array<const char*> Graphics::getRequiredExtensions() {
|
|||||||
unsigned int glfwExtensionCount = 0;
|
unsigned int glfwExtensionCount = 0;
|
||||||
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||||
|
|
||||||
|
if (glfwExtensions == nullptr || glfwExtensionCount == 0) {
|
||||||
|
const char* glfwError = nullptr;
|
||||||
|
glfwGetError(&glfwError);
|
||||||
|
std::string message = "GLFW did not report required Vulkan instance extensions";
|
||||||
|
if (glfwError != nullptr) {
|
||||||
|
message += ": ";
|
||||||
|
message += glfwError;
|
||||||
|
}
|
||||||
|
extensions.add(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
extensions.add(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
|
||||||
|
std::cerr << "Warning: " << message << ". Falling back to a default set of extensions." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < glfwExtensionCount; i++) {
|
for (unsigned int i = 0; i < glfwExtensionCount; i++) {
|
||||||
extensions.add(glfwExtensions[i]);
|
extensions.add(glfwExtensions[i]);
|
||||||
}
|
}
|
||||||
@@ -677,8 +690,16 @@ Array<const char*> Graphics::getRequiredExtensions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::initInstance(GraphicsInitializer initInfo) {
|
void Graphics::initInstance(GraphicsInitializer initInfo) {
|
||||||
glfwInit();
|
#if defined(GLFW_WAYLAND_LIBDECOR) && defined(GLFW_WAYLAND_DISABLE_LIBDECOR)
|
||||||
assert(glfwVulkanSupported());
|
// 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,
|
||||||
@@ -697,25 +718,6 @@ void Graphics::initInstance(GraphicsInitializer initInfo) {
|
|||||||
extensions.add("VK_KHR_portability_enumeration");
|
extensions.add("VK_KHR_portability_enumeration");
|
||||||
#endif
|
#endif
|
||||||
Array<const char*> layers = initInfo.layers;
|
Array<const char*> layers = initInfo.layers;
|
||||||
#ifdef ENABLE_VALIDATION
|
|
||||||
bool hasValidationLayer = false;
|
|
||||||
uint32 layerCount = 0;
|
|
||||||
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
|
||||||
Array<VkLayerProperties> availableLayers(layerCount);
|
|
||||||
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
|
|
||||||
for (const auto& layer : availableLayers) {
|
|
||||||
if (std::strcmp(layer.layerName, "VK_LAYER_KHRONOS_validation") == 0) {
|
|
||||||
hasValidationLayer = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hasValidationLayer) {
|
|
||||||
layers.add("VK_LAYER_KHRONOS_validation");
|
|
||||||
std::cerr << "Enabled Vulkan validation layer: VK_LAYER_KHRONOS_validation" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cerr << "ENABLE_VALIDATION is set, but VK_LAYER_KHRONOS_validation is unavailable on this system." << std::endl;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
VkInstanceCreateInfo info = {
|
VkInstanceCreateInfo info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
#include "Command.h"
|
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Window.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
|
|
||||||
double currentFrameDelta = 0;
|
double currentFrameDelta = 0;
|
||||||
double Gfx::getCurrentFrameDelta() { return currentFrameDelta; }
|
double Gfx::getCurrentFrameDelta() { return currentFrameDelta; }
|
||||||
|
|
||||||
@@ -60,7 +62,18 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
|||||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &contentScaleX, &contentScaleY);
|
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &contentScaleX, &contentScaleY);
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
GLFWwindow* handle = glfwCreateWindow(createInfo.width / contentScaleX, createInfo.height / contentScaleY, createInfo.title, nullptr, nullptr);
|
GLFWwindow* handle = glfwCreateWindow(createInfo.width / contentScaleX, createInfo.height / contentScaleY, createInfo.title, nullptr, nullptr);
|
||||||
|
if (handle == nullptr) {
|
||||||
|
const char* glfwError = nullptr;
|
||||||
|
glfwGetError(&glfwError);
|
||||||
|
std::string message = "Failed to create GLFW window";
|
||||||
|
if (glfwError != nullptr) {
|
||||||
|
message += ": ";
|
||||||
|
message += glfwError;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
windowHandle = handle;
|
windowHandle = handle;
|
||||||
glfwSetWindowUserPointer(handle, this);
|
glfwSetWindowUserPointer(handle, this);
|
||||||
|
|
||||||
@@ -73,7 +86,17 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
|||||||
glfwSetFramebufferSizeCallback(handle, &glfwFramebufferResizeCallback);
|
glfwSetFramebufferSizeCallback(handle, &glfwFramebufferResizeCallback);
|
||||||
// glfwSetWindowSizeCallback(handle, &glfwResizeCallback);
|
// glfwSetWindowSizeCallback(handle, &glfwResizeCallback);
|
||||||
|
|
||||||
glfwCreateWindowSurface(instance, handle, nullptr, &surface);
|
VkResult surfaceResult = glfwCreateWindowSurface(instance, handle, nullptr, &surface);
|
||||||
|
if (surfaceResult != VK_SUCCESS || surface == VK_NULL_HANDLE) {
|
||||||
|
const char* glfwError = nullptr;
|
||||||
|
glfwGetError(&glfwError);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to create Vulkan surface via GLFW (VkResult=" << surfaceResult << ")";
|
||||||
|
if (glfwError != nullptr) {
|
||||||
|
oss << ": " << glfwError;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
querySurface();
|
querySurface();
|
||||||
chooseSwapSurfaceFormat();
|
chooseSwapSurfaceFormat();
|
||||||
@@ -104,6 +127,9 @@ void Window::beginFrame() {
|
|||||||
imageAvailableFences[currentSemaphoreIndex]->getHandle(), ¤tImageIndex));
|
imageAvailableFences[currentSemaphoreIndex]->getHandle(), ¤tImageIndex));
|
||||||
imageAvailableSemaphores[currentSemaphoreIndex]->encodeSignal();
|
imageAvailableSemaphores[currentSemaphoreIndex]->encodeSignal();
|
||||||
imageAvailableFences[currentSemaphoreIndex]->submit();
|
imageAvailableFences[currentSemaphoreIndex]->submit();
|
||||||
|
// The image was reacquired, so the previous presentation using this image's
|
||||||
|
// renderDone semaphore has completed and it can be safely reused
|
||||||
|
renderingDoneSemaphores[currentImageIndex]->resolveSignal();
|
||||||
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
imageAvailableSemaphores[currentSemaphoreIndex]);
|
imageAvailableSemaphores[currentSemaphoreIndex]);
|
||||||
static double start = glfwGetTime();
|
static double start = glfwGetTime();
|
||||||
@@ -117,9 +143,9 @@ void 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);
|
||||||
renderingDoneSemaphores[currentSemaphoreIndex]->rotateSemaphore();
|
renderingDoneSemaphores[currentImageIndex]->rotateSemaphore();
|
||||||
graphics->getGraphicsCommands()->submitCommands(renderingDoneSemaphores[currentSemaphoreIndex]);
|
graphics->getGraphicsCommands()->submitCommands(renderingDoneSemaphores[currentImageIndex]);
|
||||||
VkSemaphore renderDoneHandle = renderingDoneSemaphores[currentSemaphoreIndex]->getHandle();
|
VkSemaphore renderDoneHandle = renderingDoneSemaphores[currentImageIndex]->getHandle();
|
||||||
VkPresentInfoKHR presentInfo = {
|
VkPresentInfoKHR presentInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -137,7 +163,7 @@ void Window::endFrame() {
|
|||||||
} else {
|
} else {
|
||||||
VK_CHECK(r);
|
VK_CHECK(r);
|
||||||
}
|
}
|
||||||
renderingDoneSemaphores[currentSemaphoreIndex]->resolveSignal();
|
renderingDoneSemaphores[currentImageIndex]->encodeSignal();
|
||||||
currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered;
|
currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered;
|
||||||
currentFrameIndex = currentSemaphoreIndex;
|
currentFrameIndex = currentSemaphoreIndex;
|
||||||
// graphics->waitDeviceIdle();
|
// graphics->waitDeviceIdle();
|
||||||
@@ -249,6 +275,7 @@ void Window::chooseSwapExtent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Window::createSwapChain() {
|
void Window::createSwapChain() {
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
uint32 imageCount = Gfx::numFramesBuffered;
|
uint32 imageCount = Gfx::numFramesBuffered;
|
||||||
VkSwapchainCreateInfoKHR createInfo = {
|
VkSwapchainCreateInfoKHR createInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||||
|
|||||||
+6
-5
@@ -1,9 +1,5 @@
|
|||||||
{
|
{
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
{
|
|
||||||
"name": "vulkan"
|
|
||||||
},
|
|
||||||
"vulkan-loader",
|
|
||||||
{
|
{
|
||||||
"name": "vulkan-memory-allocator"
|
"name": "vulkan-memory-allocator"
|
||||||
},
|
},
|
||||||
@@ -11,7 +7,12 @@
|
|||||||
"stb",
|
"stb",
|
||||||
"entt",
|
"entt",
|
||||||
"freetype",
|
"freetype",
|
||||||
"glfw3",
|
{
|
||||||
|
"name": "glfw3",
|
||||||
|
"features": [
|
||||||
|
"wayland"
|
||||||
|
]
|
||||||
|
},
|
||||||
"glm",
|
"glm",
|
||||||
"ktx",
|
"ktx",
|
||||||
"nlohmann-json",
|
"nlohmann-json",
|
||||||
|
|||||||
Reference in New Issue
Block a user