From 2bb75f4683f49b5f12d9e352a1d11fca63cd4170 Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Sun, 12 Mar 2023 20:39:11 +0000 Subject: [PATCH] Get rendering kind-of working again --- CMakeLists.txt | 2 + include/application.hpp | 4 +- include/gfx.hpp | 2 +- include/gfx_device.hpp | 13 ++- res/engine/shaders/test.vert | 7 +- src/application.cpp | 4 +- src/gfx_device_vulkan.cpp | 191 ++++++++++++++++++++--------------- src/systems/render.cpp | 10 +- src/vulkan/instance.cpp | 56 +++++----- src/vulkan/instance.h | 9 +- test/src/game.cpp | 22 +++- test/src/main.cpp | 2 +- 12 files changed, 192 insertions(+), 130 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bd12b0..46ea665 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.24) # options option(ENGINE_BUILD_TEST "Compile the test program" ON) +SET(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo") + project(engine LANGUAGES CXX VERSION "0.1.0" ) diff --git a/include/application.hpp b/include/application.hpp index ea65a25..46c83ed 100644 --- a/include/application.hpp +++ b/include/application.hpp @@ -65,6 +65,8 @@ namespace engine { InputManager* inputManager() { return m_inputManager.get(); } SceneManager* sceneManager() { return m_sceneManager.get(); } + gfx::DrawBuffer* getDrawBuffer() { return m_drawBuffer; } + std::string getResourcePath(const std::string relativePath) { return (m_resourcesPath / relativePath).string(); } private: @@ -77,7 +79,7 @@ namespace engine { bool m_enableFrameLimiter = true; - gfx::CommandBuffer *m_drawCommandBuffer; + gfx::DrawBuffer *m_drawBuffer; /* resource stuff */ diff --git a/include/gfx.hpp b/include/gfx.hpp index f8c66b0..84164b3 100644 --- a/include/gfx.hpp +++ b/include/gfx.hpp @@ -90,6 +90,6 @@ namespace engine::gfx { struct Pipeline; struct Buffer; struct Texture; - struct CommandBuffer; + struct DrawBuffer; } diff --git a/include/gfx_device.hpp b/include/gfx_device.hpp index a446e02..13df91d 100644 --- a/include/gfx_device.hpp +++ b/include/gfx_device.hpp @@ -19,12 +19,15 @@ namespace engine { void getViewportSize(uint32_t *w, uint32_t *h); - gfx::CommandBuffer* beginRender(); - void finishRender(gfx::CommandBuffer* commandBuffer); + gfx::DrawBuffer* beginRender(); + void finishRender(gfx::DrawBuffer* drawBuffer); - void cmdBindPipeline(gfx::CommandBuffer* commandBuffer, const gfx::Pipeline* pipeline); - void cmdBindDescriptorSetTexture(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture); - void cmdBindDescriptorSetBuffer(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture); + void cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline); + void cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer); + void cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer); + void cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); + //void cmdBindDescriptorSetTexture(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture); + //void cmdBindDescriptorSetBuffer(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture); // creates the equivalent of an OpenGL shader program & vertex attrib configuration gfx::Pipeline* createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling); diff --git a/res/engine/shaders/test.vert b/res/engine/shaders/test.vert index ebc5f11..ce7e1db 100644 --- a/res/engine/shaders/test.vert +++ b/res/engine/shaders/test.vert @@ -1,13 +1,8 @@ #version 450 -layout( push_constant ) uniform Constants { - mat4 model; - mat4 view; -} constants; - layout(location = 0) in vec3 inPosition; void main() { - gl_Position = constants.view * constants.model * vec4(inPosition, 1.0); + gl_Position = vec4(inPosition, 1.0); } diff --git a/src/application.cpp b/src/application.cpp index 3d09f4b..d250fda 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -132,7 +132,7 @@ namespace engine { while (m_window->isRunning()) { /* begin rendering */ - m_drawCommandBuffer = m_gfx->beginRender(); + m_drawBuffer = m_gfx->beginRender(); /* logic */ m_sceneManager->updateActiveScene(m_window->dt()); @@ -149,7 +149,7 @@ namespace engine { } /* draw */ - m_gfx->finishRender(m_drawCommandBuffer); + m_gfx->finishRender(m_drawBuffer); /* poll events */ m_window->getInputAndEvents(); diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp index 4ad5bd4..c6f6ae1 100644 --- a/src/gfx_device_vulkan.cpp +++ b/src/gfx_device_vulkan.cpp @@ -43,22 +43,15 @@ namespace engine { static constexpr uint32_t FRAMES_IN_FLIGHT = 2; // This improved FPS by 5x! (on Intel IGPU) static constexpr size_t PUSH_CONSTANT_MAX_SIZE = 128; // bytes + static constexpr VkIndexType INDEX_TYPE = VK_INDEX_TYPE_UINT32; // structures and enums - struct DepthBuffer { - VkImage image; - VmaAllocation allocation; - VkImageView view; - }; - - struct DrawCall { - const gfx::Pipeline* pipeline = nullptr; // for performance, keep this the same for consecutive draw calls - const gfx::Buffer* vertexBuffer = nullptr; - const gfx::Buffer* indexBuffer = nullptr; // if this is nullptr, don't use indexed - uint32_t count = 0; - uint8_t pushConstantData[PUSH_CONSTANT_MAX_SIZE]; - const gfx::Texture* texture = nullptr; + struct FrameData { + VkFence renderFence = VK_NULL_HANDLE; + VkSemaphore presentSemaphore = VK_NULL_HANDLE; + VkSemaphore renderSemaphore = VK_NULL_HANDLE; + VkCommandBuffer drawBuf = VK_NULL_HANDLE; }; // handles @@ -85,8 +78,8 @@ namespace engine { uint32_t mipLevels; }; - struct gfx::CommandBuffer { - uint32_t frameIndex; // needed to identify correct command buffer, fences and semaphores + struct gfx::DrawBuffer { + FrameData frameData; uint32_t imageIndex; // for swapchain present }; @@ -325,7 +318,7 @@ namespace engine { if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; } throw std::runtime_error("MSAA is not supported"); } - +#endif static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { [[maybe_unused]] VkResult res; @@ -373,6 +366,8 @@ namespace engine { } +#if 0 + static VkCommandBuffer beginOneTimeCommands(VkDevice device, VkCommandPool commandPool) { [[maybe_unused]] VkResult res; @@ -528,6 +523,7 @@ namespace engine { 0, nullptr, 1, &barrier); } + #endif // class definitions @@ -546,14 +542,11 @@ namespace engine { Swapchain swapchain{}; uint64_t FRAMECOUNT = 0; + + FrameData frameData[FRAMES_IN_FLIGHT] = {}; - // temp - VkFence renderFence = VK_NULL_HANDLE; - VkSemaphore presentSemaphore = VK_NULL_HANDLE; - VkSemaphore renderSemaphore = VK_NULL_HANDLE; - VkCommandBuffer drawBuf = VK_NULL_HANDLE; bool swapchainIsOutOfDate = false; - + }; GFXDevice::GFXDevice(const char* appName, const char* appVersion, SDL_Window* window, gfx::GraphicsSettings settings) @@ -579,7 +572,13 @@ namespace engine { throw std::runtime_error("The loaded Vulkan version must be at least 1.3"); } - pimpl->instance = createVulkanInstance(pimpl->window, appName, appVersion); +#ifdef NDEBUG + bool useValidation = false; +#else + bool useValidation = true; +#endif + + pimpl->instance = createVulkanInstance(pimpl->window, appName, appVersion, useValidation, MessageSeverity::SEV_WARNING); if (SDL_Vulkan_CreateSurface(pimpl->window, pimpl->instance.instance, &pimpl->surface) == false) { throw std::runtime_error("Unable to create window surface"); @@ -603,43 +602,46 @@ namespace engine { /* the following is temporary setup */ - VkFenceCreateInfo fenceInfo{ + for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + VkFenceCreateInfo fenceInfo{ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = nullptr, .flags = VK_FENCE_CREATE_SIGNALED_BIT - }; - res = vkCreateFence(pimpl->device.device, &fenceInfo, nullptr, &pimpl->renderFence); - if (res != VK_SUCCESS) throw std::runtime_error("Failed to create fence!"); + }; + res = vkCreateFence(pimpl->device.device, &fenceInfo, nullptr, &pimpl->frameData[i].renderFence); + if (res != VK_SUCCESS) throw std::runtime_error("Failed to create fence!"); - VkSemaphoreCreateInfo smphInfo{ - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - .pNext = nullptr, - .flags = 0 - }; - res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->presentSemaphore); - if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!"); - res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->renderSemaphore); - if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!"); - - // Create the command buffer for rendering: - VkCommandBufferAllocateInfo cmdAllocInfo{ - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .pNext = nullptr, - .commandPool = pimpl->device.commandPools.draw, - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = 1 - }; - VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->drawBuf)); + VkSemaphoreCreateInfo smphInfo{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = nullptr, + .flags = 0 + }; + res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].presentSemaphore); + if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!"); + res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].renderSemaphore); + if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!"); + VkCommandBufferAllocateInfo cmdAllocInfo{ + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .pNext = nullptr, + .commandPool = pimpl->device.commandPools.draw, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1 + }; + VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->frameData[i].drawBuf)); + } + } GFXDevice::~GFXDevice() { - vkFreeCommandBuffers(pimpl->device.device, pimpl->device.commandPools.draw, 1, &pimpl->drawBuf); - vkDestroySemaphore(pimpl->device.device, pimpl->renderSemaphore, nullptr); - vkDestroySemaphore(pimpl->device.device, pimpl->presentSemaphore, nullptr); - vkDestroyFence(pimpl->device.device, pimpl->renderFence, nullptr); - + for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + vkFreeCommandBuffers(pimpl->device.device, pimpl->device.commandPools.draw, 1, &pimpl->frameData[i].drawBuf); + vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].renderSemaphore, nullptr); + vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].presentSemaphore, nullptr); + vkDestroyFence(pimpl->device.device, pimpl->frameData[i].renderFence, nullptr); + } + destroySwapchain(pimpl->swapchain); destroyAllocator(pimpl->allocator); destroyDevice(pimpl->device); @@ -661,12 +663,14 @@ namespace engine { } } - gfx::CommandBuffer* GFXDevice::beginRender() + gfx::DrawBuffer* GFXDevice::beginRender() { VkResult res; uint32_t swapchainImageIndex; + FrameData frameData = pimpl->frameData[pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT]; + do { if (pimpl->swapchainIsOutOfDate) { // re-create swapchain @@ -677,19 +681,19 @@ namespace engine { // THIS FUNCTION BLOCKS UNTIL AN IMAGE IS AVAILABLE (it waits for vsync) res = vkAcquireNextImageKHR( pimpl->device.device, pimpl->swapchain.swapchain, 1000000000LL, - pimpl->presentSemaphore, VK_NULL_HANDLE, &swapchainImageIndex); + frameData.presentSemaphore, VK_NULL_HANDLE, &swapchainImageIndex); if (res != VK_SUBOPTIMAL_KHR && res != VK_ERROR_OUT_OF_DATE_KHR) VKCHECK(res); if (res == VK_SUCCESS) pimpl->swapchainIsOutOfDate = false; } while (pimpl->swapchainIsOutOfDate); /* wait until the previous frame RENDERING has finished */ - res = vkWaitForFences(pimpl->device.device, 1, &pimpl->renderFence, VK_TRUE, 1000000000LL); + res = vkWaitForFences(pimpl->device.device, 1, &frameData.renderFence, VK_TRUE, 1000000000LL); VKCHECK(res); - res = vkResetFences(pimpl->device.device, 1, &pimpl->renderFence); + res = vkResetFences(pimpl->device.device, 1, &frameData.renderFence); VKCHECK(res); /* record command buffer */ - res = vkResetCommandBuffer(pimpl->drawBuf, 0); + res = vkResetCommandBuffer(frameData.drawBuf, 0); VKCHECK(res); VkCommandBufferBeginInfo beginInfo{ @@ -698,7 +702,7 @@ namespace engine { .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, .pInheritanceInfo = nullptr // ignored }; - res = vkBeginCommandBuffer(pimpl->drawBuf, &beginInfo); + res = vkBeginCommandBuffer(frameData.drawBuf, &beginInfo); VKCHECK(res); { // RECORDING @@ -719,7 +723,7 @@ namespace engine { passBegin.renderArea.offset = { 0, 0 }; passBegin.clearValueCount = 1; passBegin.pClearValues = &clearValue; - vkCmdBeginRenderPass(pimpl->drawBuf, &passBegin, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBeginRenderPass(frameData.drawBuf, &passBegin, VK_SUBPASS_CONTENTS_INLINE); VkViewport viewport{}; viewport.x = 0.0f; @@ -728,33 +732,34 @@ namespace engine { viewport.height = -(float)pimpl->swapchain.extent.height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; - vkCmdSetViewport(pimpl->drawBuf, 0, 1, &viewport); + vkCmdSetViewport(frameData.drawBuf, 0, 1, &viewport); VkRect2D scissor{}; scissor.offset = { 0, 0 }; scissor.extent = pimpl->swapchain.extent; - vkCmdSetScissor(pimpl->drawBuf, 0, 1, &scissor); + vkCmdSetScissor(frameData.drawBuf, 0, 1, &scissor); } // hand command buffer over to caller - gfx::CommandBuffer* commandBuffer = new gfx::CommandBuffer; - commandBuffer->imageIndex = swapchainImageIndex; - return commandBuffer; + gfx::DrawBuffer* drawBuffer = new gfx::DrawBuffer; + drawBuffer->frameData = frameData; + drawBuffer->imageIndex = swapchainImageIndex; + return drawBuffer; } - void GFXDevice::finishRender(gfx::CommandBuffer* commandBuffer) + void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer) { - if (commandBuffer == nullptr) { + if (drawBuffer == nullptr) { return; } - uint32_t swapchainImageIndex = commandBuffer->imageIndex; + uint32_t swapchainImageIndex = drawBuffer->imageIndex; VkResult res; - vkCmdEndRenderPass(pimpl->drawBuf); + vkCmdEndRenderPass(drawBuffer->frameData.drawBuf); - res = vkEndCommandBuffer(pimpl->drawBuf); + res = vkEndCommandBuffer(drawBuffer->frameData.drawBuf); VKCHECK(res); // SUBMIT @@ -765,15 +770,15 @@ namespace engine { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = 1, - .pWaitSemaphores = &pimpl->presentSemaphore, + .pWaitSemaphores = &drawBuffer->frameData.presentSemaphore, .pWaitDstStageMask = &waitStage, .commandBufferCount = 1, - .pCommandBuffers = &pimpl->drawBuf, + .pCommandBuffers = &drawBuffer->frameData.drawBuf, .signalSemaphoreCount = 1, - .pSignalSemaphores = &pimpl->renderSemaphore, + .pSignalSemaphores = &drawBuffer->frameData.renderSemaphore, }; - res = vkQueueSubmit(pimpl->device.queues.drawQueues[0], 1, &submitInfo, pimpl->renderFence); - VKCHECK(res); + res = vkQueueSubmit(pimpl->device.queues.drawQueues[0], 1, &submitInfo, drawBuffer->frameData.renderFence); + // VKCHECK(res); // expensive operation for some reason // PRESENT @@ -781,7 +786,7 @@ namespace engine { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .pNext = nullptr, .waitSemaphoreCount = 1, - .pWaitSemaphores = &pimpl->renderSemaphore, + .pWaitSemaphores = &drawBuffer->frameData.renderSemaphore, .swapchainCount = 1, .pSwapchains = &pimpl->swapchain.swapchain, .pImageIndices = &swapchainImageIndex, @@ -796,7 +801,36 @@ namespace engine { pimpl->FRAMECOUNT++; - delete commandBuffer; + delete drawBuffer; + } + + void GFXDevice::cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline) + { + assert(drawBuffer != nullptr); + vkCmdBindPipeline(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle); + } + + void GFXDevice::cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer) + { + assert(drawBuffer != nullptr); + assert(buffer != nullptr); + assert(buffer->type == gfx::BufferType::VERTEX); + const VkDeviceSize offset = 0; + vkCmdBindVertexBuffers(drawBuffer->frameData.drawBuf, binding, 1, &buffer->buffer, &offset); + } + + void GFXDevice::cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer) + { + assert(drawBuffer != nullptr); + assert(buffer != nullptr); + assert(buffer->type == gfx::BufferType::INDEX); + vkCmdBindIndexBuffer(drawBuffer->frameData.drawBuf, buffer->buffer, 0, INDEX_TYPE); + } + + void GFXDevice::cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) + { + assert(drawBuffer != nullptr); + vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); } gfx::Pipeline* GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling) @@ -1037,8 +1071,6 @@ namespace engine { out->type = type; -#if 0 - VkBuffer stagingBuffer; VmaAllocation stagingAllocation; @@ -1084,20 +1116,17 @@ namespace engine { } // copy the data from the staging buffer to the gpu buffer - copyBuffer(pimpl->device, pimpl->commandPool, pimpl->gfxQueue.handle, stagingBuffer, out->buffer, out->size); + copyBuffer(pimpl->device.device, pimpl->device.commandPools.transfer, pimpl->device.queues.transferQueues[0], stagingBuffer, out->buffer, out->size); // destroy staging buffer vmaDestroyBuffer(pimpl->allocator, stagingBuffer, stagingAllocation); -#endif return out; } void GFXDevice::destroyBuffer(const gfx::Buffer* buffer) { -#if 0 vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation); -#endif delete buffer; } diff --git a/src/systems/render.cpp b/src/systems/render.cpp index ea8db8a..f8ebb6c 100644 --- a/src/systems/render.cpp +++ b/src/systems/render.cpp @@ -25,7 +25,8 @@ namespace engine { (void)ts; GFXDevice* const gfx = m_scene->app()->gfx(); - + + gfx::DrawBuffer* drawBuffer = m_scene->app()->getDrawBuffer(); /* camera stuff */ const auto cameraTransform = m_scene->getComponent(m_camera.camEntity); @@ -56,7 +57,7 @@ namespace engine { assert(r->material != nullptr); assert(r->mesh != nullptr); - assert(r->material->m_texture != nullptr); + //assert(r->material->m_texture != nullptr); struct { glm::mat4 proj; @@ -76,6 +77,11 @@ namespace engine { pushConsts.model = t->worldMatrix; pushConsts.view = viewMatrix; + gfx->cmdBindPipeline(drawBuffer, r->material->getShader()->getPipeline()); + gfx->cmdBindVertexBuffer(drawBuffer, 0, r->mesh->getVB()); + gfx->cmdBindIndexBuffer(drawBuffer, r->mesh->getIB()); + gfx->cmdDrawIndexed(drawBuffer, r->mesh->getCount(), 1, 0, 0, 0); + /* gfx->draw( r->material->getShader()->getPipeline(), diff --git a/src/vulkan/instance.cpp b/src/vulkan/instance.cpp index 5de047b..fc7e4a2 100644 --- a/src/vulkan/instance.cpp +++ b/src/vulkan/instance.cpp @@ -87,7 +87,7 @@ namespace engine { return VK_FALSE; } - static VkDebugUtilsMessengerCreateInfoEXT getDebugMessengerCreateInfo() + static VkDebugUtilsMessengerCreateInfoEXT getDebugMessengerCreateInfo(MessageSeverity validationLevel) { VkDebugUtilsMessengerCreateInfoEXT debugMessengerInfo{ .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, @@ -102,15 +102,7 @@ namespace engine { .pUserData = nullptr, }; - enum class MessageSeverity { - SEV_VERBOSE, - SEV_INFO, - SEV_WARNING, - SEV_ERROR // windows.h defines ERROR annoyingly - }; - - constexpr MessageSeverity MESSAGE_LEVEL = MessageSeverity::SEV_WARNING; - switch (MESSAGE_LEVEL) { + switch (validationLevel) { case MessageSeverity::SEV_VERBOSE: debugMessengerInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; [[fallthrough]]; @@ -130,7 +122,7 @@ namespace engine { return debugMessengerInfo; } - Instance createVulkanInstance(SDL_Window* window, const char* appName, const char* appVersion) + Instance createVulkanInstance(SDL_Window* window, const char* appName, const char* appVersion, bool useValidation, MessageSeverity validationLevel) { Instance instance; @@ -152,22 +144,31 @@ namespace engine { const std::vector windowExtensions = getWindowExtensions(window); std::vector instanceExtensionsToUse = windowExtensions; - instanceExtensionsToUse.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + if (useValidation) instanceExtensionsToUse.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - const char* const validationLayer = getValidationLayer(); + const char* validationLayer = nullptr; + if (useValidation) { + const char* validationLayer = getValidationLayer(); + } - VkDebugUtilsMessengerCreateInfoEXT debugMessengerInfo = getDebugMessengerCreateInfo(); + VkDebugUtilsMessengerCreateInfoEXT debugMessengerInfo = getDebugMessengerCreateInfo(validationLevel); VkInstanceCreateInfo instanceInfo{ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pNext = &debugMessengerInfo, - .flags = 0, - .pApplicationInfo = &applicationInfo, - .enabledLayerCount = 1, - .ppEnabledLayerNames = &validationLayer, - .enabledExtensionCount = (uint32_t)instanceExtensionsToUse.size(), - .ppEnabledExtensionNames = instanceExtensionsToUse.data(), + .flags = 0 }; + instanceInfo.pApplicationInfo = &applicationInfo; + if (validationLayer) { + instanceInfo.enabledLayerCount = 1; + instanceInfo.ppEnabledLayerNames = &validationLayer; + } + else { + instanceInfo.enabledLayerCount = 0; + instanceInfo.ppEnabledLayerNames = nullptr; + } + instanceInfo.enabledExtensionCount = (uint32_t)instanceExtensionsToUse.size(); + instanceInfo.ppEnabledExtensionNames = instanceExtensionsToUse.data(); VkResult res; res = vkCreateInstance(&instanceInfo, nullptr, &instance.instance); @@ -181,11 +182,12 @@ namespace engine { volkLoadInstanceOnly(instance.instance); // create the debug messenger - VkDebugUtilsMessengerCreateInfoEXT createInfo = getDebugMessengerCreateInfo(); - - res = vkCreateDebugUtilsMessengerEXT(instance.instance, &createInfo, nullptr, &instance.debugMessenger); - if (res != VK_SUCCESS) { - throw std::runtime_error("vkCreateDebugUtilsMessengerExt failed: " + std::to_string(res)); + if (useValidation) { + VkDebugUtilsMessengerCreateInfoEXT createInfo = getDebugMessengerCreateInfo(validationLevel); + res = vkCreateDebugUtilsMessengerEXT(instance.instance, &createInfo, nullptr, &instance.debugMessenger); + if (res != VK_SUCCESS) { + throw std::runtime_error("vkCreateDebugUtilsMessengerExt failed: " + std::to_string(res)); + } } return instance; @@ -193,7 +195,9 @@ namespace engine { void destroyVulkanInstance(Instance instance) { - vkDestroyDebugUtilsMessengerEXT(instance.instance, instance.debugMessenger, nullptr); + if (instance.debugMessenger != VK_NULL_HANDLE) { + vkDestroyDebugUtilsMessengerEXT(instance.instance, instance.debugMessenger, nullptr); + } vkDestroyInstance(instance.instance, nullptr); } diff --git a/src/vulkan/instance.h b/src/vulkan/instance.h index b27ce50..7ea210e 100644 --- a/src/vulkan/instance.h +++ b/src/vulkan/instance.h @@ -11,7 +11,14 @@ namespace engine { VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; }; - Instance createVulkanInstance(SDL_Window* window, const char* appName, const char* appVersion); + enum class MessageSeverity { + SEV_VERBOSE, + SEV_INFO, + SEV_WARNING, + SEV_ERROR // windows.h defines ERROR annoyingly + }; + + Instance createVulkanInstance(SDL_Window* window, const char* appName, const char* appVersion, bool useValidation, MessageSeverity validationLevel = MessageSeverity::SEV_WARNING); void destroyVulkanInstance(Instance instance); } \ No newline at end of file diff --git a/test/src/game.cpp b/test/src/game.cpp index c181e04..612805c 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -44,6 +44,7 @@ void playGame(bool enableFrameLimiter) engine::gfx::GraphicsSettings graphicsSettings{}; graphicsSettings.vsync = true; + graphicsSettings.waitForPresent = false; graphicsSettings.msaaLevel = engine::gfx::MSAALevel::MSAA_OFF; engine::Application app(PROJECT_NAME, PROJECT_VERSION, graphicsSettings); @@ -60,12 +61,25 @@ void playGame(bool enableFrameLimiter) const std::string fragPath = app.getResourcePath("engine/shaders/test.frag"); engine::resources::Shader::VertexParams vertexParams{}; vertexParams.hasColor = false; - vertexParams.hasNormal = false; + vertexParams.hasNormal = true; vertexParams.hasTangent = false; - vertexParams.hasUV0 = false; + vertexParams.hasUV0 = true; bool alphaBlending = false; - bool cullBackFace = false; - engine::resources::Shader testShader(app.gfx(), vertPath.c_str(), fragPath.c_str(), vertexParams, alphaBlending, cullBackFace); + bool cullBackFace = true; + auto testShader = std::make_shared(app.gfx(), vertPath.c_str(), fragPath.c_str(), vertexParams, alphaBlending, cullBackFace); + + auto camera = myScene->createEntity("camera"); + + auto renderSystem = myScene->getSystem(); + renderSystem->setCameraEntity(camera); + myScene->getComponent(camera)->position = { 0.0f, 10.0f, 0.0f }; + + /* cube */ + uint32_t cube = myScene->createEntity("cube"); + myScene->getComponent(cube)->position = glm::vec3{ -0.5f, -0.5f, -0.5f }; + auto cubeRenderable = myScene->addComponent(cube); + cubeRenderable->material = std::make_shared(testShader); + cubeRenderable->mesh = genCuboidMesh(app.gfx(), 1, 1.0f, 1, 1); #if 0 diff --git a/test/src/main.cpp b/test/src/main.cpp index 20efa54..6f9472b 100644 --- a/test/src/main.cpp +++ b/test/src/main.cpp @@ -14,7 +14,7 @@ int main(int argc, char* argv[]) bool enableFrameLimiter = true; if (argc == 2) { - if (strcmp(argv[2], "nofpslimit") == 0) enableFrameLimiter = false; + if (strcmp(argv[1], "nofpslimit") == 0) enableFrameLimiter = false; } engine::setupLog(PROJECT_NAME);