diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index eb39c967..4820f9a3 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -13,8 +13,45 @@ #include "FrameContext.h" namespace MobileGL::MG_Backend::DirectVulkan { + VkBool32 VulkanRenderer::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { + auto typeToString = [](VkDebugUtilsMessageTypeFlagsEXT messageType) { + switch (messageType) { + case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: + return "General"; + case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: + return "Validation"; + case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: + return "Performance"; + case VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT: + return "DeviceAddressBinding"; + default: + return "Other"; + } + }; + + switch (messageSeverity) { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + MGLOG_E("Vulkan Debug: [%s] %s", typeToString(messageType), pCallbackData->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + MGLOG_W("Vulkan Debug: [%s] %s", typeToString(messageType), pCallbackData->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + MGLOG_I("Vulkan Debug: [%s] %s", typeToString(messageType), pCallbackData->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + MGLOG_D("Vulkan Debug: [%s] %s", typeToString(messageType), pCallbackData->pMessage); + break; + default: + break; + } + return VK_FALSE; + } + VulkanRenderer::VulkanRenderer(NativeWindowType window, const RendererConfig& cfg) : m_window(window), m_config(cfg) { - m_context = std::make_unique(); + Initialize(); } VulkanRenderer::~VulkanRenderer() { @@ -22,282 +59,159 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void VulkanRenderer::Initialize() { - m_context->Initialize(m_window, m_config.AppName); - - m_swapchain = std::make_unique(*m_context); - m_swapchain->Initialize(); - - CreateRenderPass(); - - m_pipelineMgr = std::make_unique(*m_context); - - CreateCommandPool(); - CreateFrameResources(); - + CreateInstance(); MGLOG_D("VulkanRenderer initialized"); } void VulkanRenderer::Shutdown() { - if (!m_context) return; - - if (m_context->GetDevice() == VK_NULL_HANDLE) return; - - vkDeviceWaitIdle(m_context->GetDevice()); - - DestroyFrameResources(); - DestroyCommandPool(); - - if (m_pipelineMgr) { - m_pipelineMgr->Cleanup(); - m_pipelineMgr.reset(); + if (m_debugMessenger != VK_NULL_HANDLE) { + DestroyDebugMessenger(); } - DestroyRenderPass(); - if (m_swapchain) { - m_swapchain->Cleanup(); - m_swapchain.reset(); - } - if (m_context) { - m_context->Shutdown(); - m_context.reset(); - } - MGLOG_D("VulkanRenderer shutdown"); + DestroyInstance(); + MGLOG_D("VulkanRenderer shut down completed"); } - void VulkanRenderer::CreateRenderPass() { - VkAttachmentDescription color{}; - color.format = m_swapchain->GetFormat(); - color.samples = VK_SAMPLE_COUNT_1_BIT; - color.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - color.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + void VulkanRenderer::Render() { - VkAttachmentReference colorRef{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - VkSubpassDescription sub{}; - sub.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - sub.colorAttachmentCount = 1; - sub.pColorAttachments = &colorRef; - - VkRenderPassCreateInfo rpci{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO}; - rpci.attachmentCount = 1; - rpci.pAttachments = &color; - rpci.subpassCount = 1; - rpci.pSubpasses = ⊂ - - VK_VERIFY(vkCreateRenderPass(m_context->GetDevice(), &rpci, nullptr, &m_renderPass), "vkCreateRenderPass"); - - // Create framebuffers now (use swapchain imageviews) - const auto& imageViews = m_swapchain->GetImageViews(); - std::vector fbs; - fbs.reserve(imageViews.size()); - for (auto iv : imageViews) { - VkImageView attachments[] = {iv}; - VkFramebufferCreateInfo fbci{VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO}; - fbci.renderPass = m_renderPass; - fbci.attachmentCount = 1; - fbci.pAttachments = attachments; - fbci.width = m_swapchain->GetExtent().width; - fbci.height = m_swapchain->GetExtent().height; - fbci.layers = 1; - VkFramebuffer fb; - VK_VERIFY(vkCreateFramebuffer(m_context->GetDevice(), &fbci, nullptr, &fb), "vkCreateFramebuffer"); - fbs.push_back(fb); - } - m_swapchain->SetFramebuffers(std::move(fbs)); - MGLOG_D("RenderPass created and framebuffers set"); - } - - void VulkanRenderer::DestroyRenderPass() { - if (m_renderPass != VK_NULL_HANDLE) { - vkDestroyRenderPass(m_context->GetDevice(), m_renderPass, nullptr); - m_renderPass = VK_NULL_HANDLE; - } - } - - void VulkanRenderer::CreateCommandPool() { - VkCommandPoolCreateInfo cpci{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO}; - cpci.queueFamilyIndex = m_context->GetGraphicsQueueFamily(); - cpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_VERIFY(vkCreateCommandPool(m_context->GetDevice(), &cpci, nullptr, &m_commandPool), "vkCreateCommandPool"); - } - - void VulkanRenderer::DestroyCommandPool() { - if (m_commandPool != VK_NULL_HANDLE) { - vkDestroyCommandPool(m_context->GetDevice(), m_commandPool, nullptr); - m_commandPool = VK_NULL_HANDLE; - } - } - - void VulkanRenderer::CreateFrameResources() { - uint32_t imageCount = static_cast(m_swapchain->GetImageViews().size()); - if (imageCount == 0) throw RuntimeError("Swapchain has zero images"); - uint32_t frames = std::min(m_config.MaxFramesInFlight, imageCount); - m_frames.clear(); - for (uint32_t i = 0; i < frames; ++i) { - auto fr = std::make_unique(); - fr->Initialize(*m_context, m_commandPool); - m_frames.push_back(std::move(fr)); - } - m_currentFrame = 0; - MGLOG_D("FrameResources created: %u", (uint32_t)Frames.size()); - } - - void VulkanRenderer::DestroyFrameResources() { - for (auto& f : m_frames) { - if (f) f->Cleanup(*m_context); - } - m_frames.clear(); - } - - void VulkanRenderer::RecordFrameCommandBuffer(FrameContext& frame, uint32_t imageIndex) { - // Begin - VkCommandBufferBeginInfo bi{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}; - VK_VERIFY(vkBeginCommandBuffer(frame.CommandBuffer, &bi), "vkBeginCommandBuffer"); - - VkClearValue clear{}; - clear.color = {{0.0f, 0.0f, 0.0f, 1.0f}}; - VkRenderPassBeginInfo rpbi{VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO}; - rpbi.renderPass = m_renderPass; - rpbi.framebuffer = m_swapchain->GetFramebuffers()[imageIndex]; - rpbi.renderArea.offset = {0, 0}; - rpbi.renderArea.extent = m_swapchain->GetExtent(); - rpbi.clearValueCount = 1; - rpbi.pClearValues = &clear; - - vkCmdBeginRenderPass(frame.CommandBuffer, &rpbi, VK_SUBPASS_CONTENTS_INLINE); - - for (auto& kv : m_renderCallbacks) { - if (kv.second) { - kv.second(frame.CommandBuffer, imageIndex, m_swapchain->GetExtent()); - } - } - - vkCmdEndRenderPass(frame.CommandBuffer); - VK_VERIFY(vkEndCommandBuffer(frame.CommandBuffer), "vkEndCommandBuffer"); - } - - void VulkanRenderer::RecreateSwapchainIfNeeded() { - vkDeviceWaitIdle(m_context->GetDevice()); - DestroyFrameResources(); - DestroyRenderPass(); - m_swapchain->Recreate(); - CreateRenderPass(); - CreateFrameResources(); - } - - // Wait fence & Acquire image & Record commands & Submit - void VulkanRenderer::RenderFrame() { - if (!m_context) throw RuntimeError("Renderer not initialized"); - FrameContext& frame = *m_frames[m_currentFrame]; - - // Ensure the previous use of this frame context has fully completed - // before reusing its semaphores in vkAcquireNextImageKHR. - VK_VERIFY(vkWaitForFences(m_context->GetDevice(), 1, &frame.InFlightFence, VK_TRUE, UINT64_MAX), "vkWaitForFences"); - - if (!FrameBegin()) return; - - // Fence will be signaled by vkQueueSubmit below. - VK_VERIFY(vkResetFences(m_context->GetDevice(), 1, &frame.InFlightFence), "vkResetFences"); - - // Record commands - VK_VERIFY(vkResetCommandBuffer(frame.CommandBuffer, 0), "vkResetCommandBuffer"); - RecordFrameCommandBuffer(frame, frame.CurrentImageIndex); - - // Submit - VkSubmitInfo si{VK_STRUCTURE_TYPE_SUBMIT_INFO}; - VkSemaphore waitSemaphores[] = {frame.ImageAvailable}; - VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - si.waitSemaphoreCount = 1; - si.pWaitSemaphores = waitSemaphores; - si.pWaitDstStageMask = waitStages; - si.commandBufferCount = 1; - si.pCommandBuffers = &frame.CommandBuffer; - VkSemaphore signalSemaphores[] = {frame.RenderFinished}; - si.signalSemaphoreCount = 1; - si.pSignalSemaphores = signalSemaphores; - - VK_VERIFY(vkQueueSubmit(m_context->GetGraphicsQueue(), 1, &si, frame.InFlightFence), "vkQueueSubmit"); - } - - bool VulkanRenderer::FrameBegin() { - FrameContext& frame = *m_frames[m_currentFrame]; - - while (true) { - // Acquire image for this frame. Acquire can fail with OUT_OF_DATE during resize/minimize. - Uint32 imageIndex = 0; - VkResult res = vkAcquireNextImageKHR(m_context->GetDevice(), m_swapchain->GetSwapchain(), UINT64_MAX, - frame.ImageAvailable, VK_NULL_HANDLE, &imageIndex); - - if (res == VK_ERROR_OUT_OF_DATE_KHR) { - MGLOG_D("vkAcquireNextImageKHR: OUT_OF_DATE -> recreate"); - RecreateSwapchainIfNeeded(); - continue; - } - if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) { - VK_VERIFY(res, "vkAcquireNextImageKHR"); - return false; - } - - auto& imagesInFlight = m_swapchain->GetImagesInFlight(); - if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) { - vkWaitForFences(m_context->GetDevice(), 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX); - } - imagesInFlight[imageIndex] = frame.InFlightFence; - frame.CurrentImageIndex = imageIndex; - return true; - } } void VulkanRenderer::Present() { - if (!m_context) throw RuntimeError("Renderer not initialized"); - FrameContext& frame = *m_frames[m_currentFrame]; - // Present - VkPresentInfoKHR pi{VK_STRUCTURE_TYPE_PRESENT_INFO_KHR}; - VkSemaphore signalSemaphores[] = {frame.RenderFinished}; - pi.waitSemaphoreCount = 1; - pi.pWaitSemaphores = signalSemaphores; - VkSwapchainKHR scs[] = {m_swapchain->GetSwapchain()}; - pi.swapchainCount = 1; - pi.pSwapchains = scs; - pi.pImageIndices = &frame.CurrentImageIndex; - VkResult pres = vkQueuePresentKHR(m_context->GetGraphicsQueue(), &pi); - if (pres == VK_ERROR_OUT_OF_DATE_KHR || pres == VK_SUBOPTIMAL_KHR) { - MGLOG_D("vkQueuePresentKHR: out_of_date/suboptimal -> recreate"); - RecreateSwapchainIfNeeded(); + } + + void VulkanRenderer::CreateInstance() { + m_extensions = EnumerateExtensions(); + MGLOG_I("Got %d Vulkan extensions: ", m_extensions.size()); + for (auto& extension : m_extensions) { + MGLOG_I(" %s (r.%u)", extension.extensionName, extension.specVersion); + } + + Bool validationLayerAvailable = CheckValidationLayerSupport(); + MGLOG_D("Validation layers %s.", validationLayerAvailable ? "available" : "not available"); + MGLOG_D("Validation layers %s.", m_config.EnableValidationLayers ? "requested" : "not requested"); + + if (m_config.EnableValidationLayers && !validationLayerAvailable) { + MOBILEGL_ASSERT(false, "Validation layers requested but not available!"); + } + + bool enableValidationLayers = m_config.EnableValidationLayers && validationLayerAvailable; + + // ---------------- App info ------------------- + VkApplicationInfo appInfo = {}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = m_config.AppName.c_str(); + appInfo.applicationVersion = VK_MAKE_VERSION(m_config.CacheVersion, 0, 0); + appInfo.pEngineName = "MobileGL"; + appInfo.engineVersion = VK_MAKE_VERSION(m_config.Version.Major, m_config.Version.Minor, m_config.Version.Patch); +#ifdef VK_USE_PLATFORM_WIN32_KHR + appInfo.apiVersion = VK_API_VERSION_1_3; +#else + appInfo.apiVersion = VK_API_VERSION_1_1; +#endif + + + // ---------------- Instance info ------------------- + VkInstanceCreateInfo instanceInfo = {}; + instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instanceInfo.pApplicationInfo = &appInfo; + + // Extensions + Vector exts = {VK_KHR_SURFACE_EXTENSION_NAME, +#ifdef VK_USE_PLATFORM_ANDROID_KHR + VK_KHR_ANDROID_SURFACE_EXTENSION_NAME +#elif defined VK_USE_PLATFORM_WIN32_KHR + VK_KHR_WIN32_SURFACE_EXTENSION_NAME +#else +#warning "VulkanContext::CreateInstance: VK_KHR_*_surface extension not defined on this platform" +#endif +}; // TODO: support more platforms + + if (enableValidationLayers) { + exts.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + + instanceInfo.enabledExtensionCount = exts.size(); + instanceInfo.ppEnabledExtensionNames = exts.data(); + + auto debugMessengerCreateInfo = PopulateDebugMessengerCreateInfo(); + // Layers + if (enableValidationLayers) { + MGLOG_I("Enabling validation layer."); + instanceInfo.enabledLayerCount = static_cast(std::size(s_validationLayerNames)); + instanceInfo.ppEnabledLayerNames = s_validationLayerNames; + instanceInfo.pNext = &debugMessengerCreateInfo; } else { - VK_VERIFY(pres, "vkQueuePresentKHR"); + instanceInfo.enabledLayerCount = 0; + instanceInfo.pNext = nullptr; } - m_currentFrame = (m_currentFrame + 1) % m_frames.size(); + VK_VERIFY(vkCreateInstance(&instanceInfo, nullptr, &m_instance), "vkCreateInstance failed"); + + if (enableValidationLayers) + VK_VERIFY(SetupDebugMessenger()); } - void VulkanRenderer::RegisterRenderCallback(const String& name, RenderCallback cb) { - auto it = std::find_if(m_renderCallbacks.begin(), m_renderCallbacks.end(), - [&](const auto& kv) { return kv.first == name; }); - if (it != m_renderCallbacks.end()) { - MGLOG_W("Render callback '%s' already registered", name.c_str()); - return; + void VulkanRenderer::DestroyInstance() { + if (m_instance != VK_NULL_HANDLE) { + vkDestroyInstance(m_instance, nullptr); + m_instance = VK_NULL_HANDLE; } - m_renderCallbacks.emplace_back(name, std::move(cb)); } - void VulkanRenderer::UnregisterRenderCallback(const String& name) { - m_renderCallbacks.erase(std::remove_if(m_renderCallbacks.begin(), m_renderCallbacks.end(), - [&](const auto& kv) { return kv.first == name; }), - m_renderCallbacks.end()); + VkResult VulkanRenderer::SetupDebugMessenger() { + auto createInfo = PopulateDebugMessengerCreateInfo(); + auto vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(m_instance, "vkCreateDebugUtilsMessengerEXT"); + if (!vkCreateDebugUtilsMessengerEXT) + return VK_ERROR_EXTENSION_NOT_PRESENT; + VK_VERIFY(vkCreateDebugUtilsMessengerEXT(m_instance, &createInfo, nullptr, &m_debugMessenger)); + return VK_SUCCESS; } - VkPipeline VulkanRenderer::CreateGraphicsPipelineFromSpv(const String& key, const Vector& vsSpv, - const Vector& fsSpv) { - return m_pipelineMgr->CreateGraphicsPipelineFromSpv(key, vsSpv, fsSpv, m_renderPass, m_swapchain->GetExtent()); + VkResult VulkanRenderer::DestroyDebugMessenger() { + if (m_debugMessenger != VK_NULL_HANDLE) { + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(m_instance, "vkDestroyDebugUtilsMessengerEXT"); + if (func != nullptr) { + func(m_instance, m_debugMessenger, nullptr); + } else { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + } + return VK_SUCCESS; } - VkExtent2D VulkanRenderer::GetExtent() const { - return m_swapchain ? m_swapchain->GetExtent() : VkExtent2D{0, 0}; + VkDebugUtilsMessengerCreateInfoEXT VulkanRenderer::PopulateDebugMessengerCreateInfo() { + VkDebugUtilsMessengerCreateInfoEXT createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + createInfo.pfnUserCallback = DebugCallback; + createInfo.pUserData = this; + return createInfo; } - void VulkanRenderer::WaitIdle() { - if (m_context && m_context->GetDevice() != VK_NULL_HANDLE) vkDeviceWaitIdle(m_context->GetDevice()); + Vector VulkanRenderer::EnumerateExtensions() { + Uint32 extensionCount = 0; + VK_VERIFY(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr)); + Vector extensions(extensionCount); + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); + return extensions; } + + Bool VulkanRenderer::CheckValidationLayerSupport() { + Uint32 layerCount = 0; + VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, nullptr)); + + Vector layers(layerCount); + VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, layers.data())); + + for (const char* layerName : s_validationLayerNames) { + for (const auto& layerProperties : layers) { + if (strcmp(layerName, layerProperties.layerName) == 0) { + return true; + } + } + } + return false; + } + } // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 8c17ef8c..5eb5247b 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -7,8 +7,15 @@ // End of Source File Header #pragma once +#include "Config.h" #include +#define VK_VERIFY(expr, ...) \ + do { \ + VkResult _vk_verify_result = (expr); \ + MOBILEGL_ASSERT(_vk_verify_result == VK_SUCCESS, "Vulkan error %d at %s:%d" __VA_OPT__(" - ") __VA_ARGS__, _vk_verify_result, __FILE__, __LINE__); \ + } while (0) + namespace MobileGL::MG_Backend::DirectVulkan { class VulkanContext; class SwapchainManager; @@ -20,6 +27,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { struct RendererConfig { Uint32 MaxFramesInFlight = 2; String AppName = "MobileGL-VulkanRenderer"; + Version Version = MG_Config::CoreVersion; + Uint64 CacheVersion = MG_Config::CacheVersion; + Bool EnableValidationLayers = true; }; class VulkanRenderer { @@ -30,45 +40,33 @@ namespace MobileGL::MG_Backend::DirectVulkan { void Initialize(); void Shutdown(); - void RenderFrame(); + void Render(); void Present(); - void RegisterRenderCallback(const String& name, RenderCallback cb); - void UnregisterRenderCallback(const String& name); - - VkPipeline CreateGraphicsPipelineFromSpv(const String& key, const Vector& vsSpv, - const Vector& fsSpv); - - VkExtent2D GetExtent() const; - - void WaitIdle(); - private: NativeWindowType m_window = 0; RendererConfig m_config; - UniquePtr m_context; - UniquePtr m_swapchain; - UniquePtr m_pipelineMgr; + // Vulkan objects + Vector m_extensions; + VkInstance m_instance = VK_NULL_HANDLE; + VkDebugUtilsMessengerEXT m_debugMessenger = VK_NULL_HANDLE; - VkRenderPass m_renderPass = VK_NULL_HANDLE; - VkCommandPool m_commandPool = VK_NULL_HANDLE; + void CreateInstance(); + void DestroyInstance(); + VkResult SetupDebugMessenger(); + VkResult DestroyDebugMessenger(); + VkDebugUtilsMessengerCreateInfoEXT PopulateDebugMessengerCreateInfo(); + static Vector EnumerateExtensions(); + static constexpr const char* s_validationLayerNames[] = { + "VK_LAYER_KHRONOS_validation" + }; + static Bool CheckValidationLayerSupport(); - Vector> m_frames; - Uint32 m_currentFrame = 0; - - // Render callbacks map - Vector> m_renderCallbacks; - - // Internals - void CreateRenderPass(); - void DestroyRenderPass(); - void CreateCommandPool(); - void DestroyCommandPool(); - void CreateFrameResources(); - void DestroyFrameResources(); - void RecordFrameCommandBuffer(FrameContext& frame, uint32_t imageIndex); - void RecreateSwapchainIfNeeded(); - bool FrameBegin(); + static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData); }; } // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp b/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp index 266e6535..19cb040f 100644 --- a/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp +++ b/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp @@ -75,16 +75,16 @@ namespace MobileGL { } // Create pipeline - VkPipeline trianglePipeline = MG_Backend::DirectVulkan::pVulkanRenderer->CreateGraphicsPipelineFromSpv( - "TrianglePipeline", vsSpv, fsSpv); - - // Register render callback - MG_Backend::DirectVulkan::pVulkanRenderer->RegisterRenderCallback( - "DrawTriangle", [trianglePipeline](VkCommandBuffer cmd, uint32_t imageIndex, VkExtent2D extent) { - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, trianglePipeline); - - vkCmdDraw(cmd, 3, 1, 0, 0); - }); + // VkPipeline trianglePipeline = MG_Backend::DirectVulkan::pVulkanRenderer->CreateGraphicsPipelineFromSpv( + // "TrianglePipeline", vsSpv, fsSpv); + // + // // Register render callback + // MG_Backend::DirectVulkan::pVulkanRenderer->RegisterRenderCallback( + // "DrawTriangle", [trianglePipeline](VkCommandBuffer cmd, uint32_t imageIndex, VkExtent2D extent) { + // vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, trianglePipeline); + // + // vkCmdDraw(cmd, 3, 1, 0, 0); + // }); } void CreateWindowSurfaceForVulkan(NativeWindowType window) { @@ -106,8 +106,6 @@ namespace MobileGL { MGLOG_E("EGLForVulkan::SwapBuffers called but VulkanRenderer is null"); return EGL_FALSE; } - // TODO: replace this with real rendering code - MG_Backend::DirectVulkan::pVulkanRenderer->RenderFrame(); MG_Backend::DirectVulkan::pVulkanRenderer->Present(); return EGL_TRUE; }