mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Chore] (MG_Test/Backend/DirectVulkan): encapsulate SwapchainObject
This commit is contained in:
@@ -0,0 +1,138 @@
|
|||||||
|
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/SwapchainObject.cpp
|
||||||
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||||
|
// Licensed under the GNU Lesser General Public License v3.0:
|
||||||
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
// End of Source File Header
|
||||||
|
|
||||||
|
#include "SwapchainObject.h"
|
||||||
|
|
||||||
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
SwapchainObject::SwapchainCapabilities SwapchainObject::GetSwapchainCapabilities(VkPhysicalDevice physicalDevice,
|
||||||
|
VkSurfaceKHR surface) {
|
||||||
|
SwapchainCapabilities swapchainCapabilities{};
|
||||||
|
|
||||||
|
VK_VERIFY(
|
||||||
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &swapchainCapabilities.capabilities));
|
||||||
|
|
||||||
|
Uint32 formatCount = 0;
|
||||||
|
VK_VERIFY(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, nullptr));
|
||||||
|
if (formatCount != 0) {
|
||||||
|
swapchainCapabilities.surfaceFormats.resize(formatCount);
|
||||||
|
VK_VERIFY(vkGetPhysicalDeviceSurfaceFormatsKHR(
|
||||||
|
physicalDevice, surface, &formatCount, swapchainCapabilities.surfaceFormats.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 presentModeCount = 0;
|
||||||
|
VK_VERIFY(
|
||||||
|
vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, nullptr));
|
||||||
|
if (presentModeCount != 0) {
|
||||||
|
swapchainCapabilities.presentModes.resize(presentModeCount);
|
||||||
|
VK_VERIFY(vkGetPhysicalDeviceSurfacePresentModesKHR(
|
||||||
|
physicalDevice, surface, &presentModeCount, swapchainCapabilities.presentModes.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return swapchainCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSurfaceFormatKHR SwapchainObject::ChooseSwapchainSurfaceFormat(
|
||||||
|
const Vector<VkSurfaceFormatKHR>& availableFormats) {
|
||||||
|
for (const auto& availableFormat : availableFormats) {
|
||||||
|
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB &&
|
||||||
|
availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||||
|
return availableFormat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Properly rank other formats
|
||||||
|
return availableFormats[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentModeKHR SwapchainObject::ChooseSwapchainPresentMode(
|
||||||
|
const Vector<VkPresentModeKHR>& availablePresentModes) {
|
||||||
|
for (auto desiredPresentMode : s_desiredPresentModes) {
|
||||||
|
for (const auto& presentMode : availablePresentModes) {
|
||||||
|
if (presentMode == desiredPresentMode) {
|
||||||
|
return presentMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Properly rank other modes
|
||||||
|
return availablePresentModes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapchainObject::Create(VkDevice device, const VkSwapchainCreateInfoKHR& createInfo) {
|
||||||
|
m_surfaceFormat = {createInfo.imageFormat, createInfo.imageColorSpace};
|
||||||
|
m_extent = createInfo.imageExtent;
|
||||||
|
|
||||||
|
VK_VERIFY(vkCreateSwapchainKHR(device, &createInfo, nullptr, &m_swapchain));
|
||||||
|
|
||||||
|
Uint32 imageCount = 0;
|
||||||
|
VK_VERIFY(vkGetSwapchainImagesKHR(device, m_swapchain, &imageCount, nullptr));
|
||||||
|
|
||||||
|
m_images.resize(imageCount, VK_NULL_HANDLE);
|
||||||
|
VK_VERIFY(vkGetSwapchainImagesKHR(device, m_swapchain, &imageCount, m_images.data()));
|
||||||
|
m_imageLayouts.assign(imageCount, VK_IMAGE_LAYOUT_UNDEFINED);
|
||||||
|
|
||||||
|
CreateImageViews(device);
|
||||||
|
|
||||||
|
MGLOG_I("Swapchain created, extent = %dx%d, swapchain imageCount = %d", m_extent.width, m_extent.height,
|
||||||
|
imageCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapchainObject::Shutdown(VkDevice device) {
|
||||||
|
for (auto imageView : m_imageViews) {
|
||||||
|
vkDestroyImageView(device, imageView, nullptr);
|
||||||
|
}
|
||||||
|
m_imageViews.clear();
|
||||||
|
|
||||||
|
if (m_swapchain != VK_NULL_HANDLE) {
|
||||||
|
vkDestroySwapchainKHR(device, m_swapchain, nullptr);
|
||||||
|
m_swapchain = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_images.clear();
|
||||||
|
m_imageLayouts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImage SwapchainObject::GetImage(Uint32 index) const {
|
||||||
|
MOBILEGL_ASSERT(index < m_images.size(), "Swapchain image index out of range");
|
||||||
|
return m_images[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageLayout SwapchainObject::GetImageLayout(Uint32 index) const {
|
||||||
|
MOBILEGL_ASSERT(index < m_imageLayouts.size(), "Swapchain image layout index out of range");
|
||||||
|
return m_imageLayouts[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapchainObject::SetImageLayout(Uint32 index, VkImageLayout layout) {
|
||||||
|
MOBILEGL_ASSERT(index < m_imageLayouts.size(), "Swapchain image layout index out of range");
|
||||||
|
m_imageLayouts[index] = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapchainObject::CreateImageViews(VkDevice device) {
|
||||||
|
m_imageViews.resize(m_images.size(), VK_NULL_HANDLE);
|
||||||
|
for (SizeT i = 0; i < m_imageViews.size(); i++) {
|
||||||
|
VkImageViewCreateInfo createInfo{};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
createInfo.image = m_images[i];
|
||||||
|
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
createInfo.format = m_surfaceFormat.format;
|
||||||
|
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
createInfo.subresourceRange.baseMipLevel = 0;
|
||||||
|
createInfo.subresourceRange.levelCount = 1;
|
||||||
|
createInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
|
createInfo.subresourceRange.layerCount = 1;
|
||||||
|
VK_VERIFY(vkCreateImageView(device, &createInfo, nullptr, &m_imageViews[i]));
|
||||||
|
}
|
||||||
|
MGLOG_I("Swapchain image views created");
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef VK_VERIFY
|
||||||
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/SwapchainObject.h
|
||||||
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||||
|
// Licensed under the GNU Lesser General Public License v3.0:
|
||||||
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
// End of Source File Header
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Includes.h>
|
||||||
|
#include "../VkIncludes.h"
|
||||||
|
|
||||||
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
class SwapchainObject {
|
||||||
|
public:
|
||||||
|
struct SwapchainCapabilities {
|
||||||
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
|
Vector<VkSurfaceFormatKHR> surfaceFormats;
|
||||||
|
Vector<VkPresentModeKHR> presentModes;
|
||||||
|
|
||||||
|
Bool IsComplete() const {
|
||||||
|
return !surfaceFormats.empty() && !presentModes.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static SwapchainCapabilities GetSwapchainCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface);
|
||||||
|
static VkSurfaceFormatKHR ChooseSwapchainSurfaceFormat(const Vector<VkSurfaceFormatKHR>& availableFormats);
|
||||||
|
static VkPresentModeKHR ChooseSwapchainPresentMode(const Vector<VkPresentModeKHR>& availablePresentModes);
|
||||||
|
|
||||||
|
void Create(VkDevice device, const VkSwapchainCreateInfoKHR& createInfo);
|
||||||
|
void Shutdown(VkDevice device);
|
||||||
|
|
||||||
|
VkSwapchainKHR GetHandle() const { return m_swapchain; }
|
||||||
|
const VkSurfaceFormatKHR& GetSurfaceFormat() const { return m_surfaceFormat; }
|
||||||
|
VkExtent2D GetExtent() const { return m_extent; }
|
||||||
|
const Vector<VkImage>& GetImages() const { return m_images; }
|
||||||
|
const Vector<VkImageView>& GetImageViews() const { return m_imageViews; }
|
||||||
|
VkImage GetImage(Uint32 index) const;
|
||||||
|
VkImageLayout GetImageLayout(Uint32 index) const;
|
||||||
|
void SetImageLayout(Uint32 index, VkImageLayout layout);
|
||||||
|
SizeT GetImageCount() const { return m_images.size(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateImageViews(VkDevice device);
|
||||||
|
static constexpr VkPresentModeKHR s_desiredPresentModes[] {
|
||||||
|
VK_PRESENT_MODE_MAILBOX_KHR,
|
||||||
|
VK_PRESENT_MODE_IMMEDIATE_KHR,
|
||||||
|
VK_PRESENT_MODE_FIFO_RELAXED_KHR,
|
||||||
|
VK_PRESENT_MODE_FIFO_KHR
|
||||||
|
};
|
||||||
|
|
||||||
|
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
||||||
|
VkSurfaceFormatKHR m_surfaceFormat{};
|
||||||
|
VkExtent2D m_extent{};
|
||||||
|
Vector<VkImage> m_images;
|
||||||
|
Vector<VkImageView> m_imageViews;
|
||||||
|
Vector<VkImageLayout> m_imageLayouts;
|
||||||
|
};
|
||||||
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
@@ -168,11 +168,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkViewport vp{};
|
VkViewport vp{};
|
||||||
vp.x = 0;
|
vp.x = 0;
|
||||||
vp.y = 0;
|
vp.y = 0;
|
||||||
vp.width = (float)m_swapchainExtent.width;
|
const auto swapchainExtent = m_swapchainObject.GetExtent();
|
||||||
vp.height = (float)m_swapchainExtent.height;
|
vp.width = (float)swapchainExtent.width;
|
||||||
|
vp.height = (float)swapchainExtent.height;
|
||||||
vp.minDepth = 0;
|
vp.minDepth = 0;
|
||||||
vp.maxDepth = 1;
|
vp.maxDepth = 1;
|
||||||
VkRect2D scissor{{0, 0}, m_swapchainExtent};
|
VkRect2D scissor{{0, 0}, swapchainExtent};
|
||||||
VkPipelineViewportStateCreateInfo vpci{VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
|
VkPipelineViewportStateCreateInfo vpci{VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
|
||||||
vpci.viewportCount = 1;
|
vpci.viewportCount = 1;
|
||||||
vpci.pViewports = &vp;
|
vpci.pViewports = &vp;
|
||||||
@@ -256,7 +257,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
// Prime the first frame so Render() always targets an acquired swapchain image.
|
// Prime the first frame so Render() always targets an acquired swapchain image.
|
||||||
VK_VERIFY(vkWaitForFences(m_device, 1, &m_imageInFlightFences[m_currentFrameIndex], VK_TRUE, UINT64_MAX));
|
VK_VERIFY(vkWaitForFences(m_device, 1, &m_imageInFlightFences[m_currentFrameIndex], VK_TRUE, UINT64_MAX));
|
||||||
VK_VERIFY(vkResetFences(m_device, 1, &m_imageInFlightFences[m_currentFrameIndex]));
|
VK_VERIFY(vkResetFences(m_device, 1, &m_imageInFlightFences[m_currentFrameIndex]));
|
||||||
VK_VERIFY(vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX,
|
VK_VERIFY(vkAcquireNextImageKHR(m_device, m_swapchainObject.GetHandle(), UINT64_MAX,
|
||||||
m_imageAvailableSemaphores[m_currentFrameIndex], VK_NULL_HANDLE,
|
m_imageAvailableSemaphores[m_currentFrameIndex], VK_NULL_HANDLE,
|
||||||
&m_imageIndexAcquired));
|
&m_imageIndexAcquired));
|
||||||
|
|
||||||
@@ -335,7 +336,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
renderPassInfo.renderPass = m_renderPass;
|
renderPassInfo.renderPass = m_renderPass;
|
||||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
||||||
renderPassInfo.renderArea.offset = {0, 0};
|
renderPassInfo.renderArea.offset = {0, 0};
|
||||||
renderPassInfo.renderArea.extent = m_swapchainExtent;
|
const auto swapchainExtent = m_swapchainObject.GetExtent();
|
||||||
|
renderPassInfo.renderArea.extent = swapchainExtent;
|
||||||
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
||||||
renderPassInfo.clearValueCount = 1;
|
renderPassInfo.clearValueCount = 1;
|
||||||
renderPassInfo.pClearValues = &clearColor;
|
renderPassInfo.pClearValues = &clearColor;
|
||||||
@@ -347,15 +349,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkViewport viewport{};
|
VkViewport viewport{};
|
||||||
viewport.x = 0.0f;
|
viewport.x = 0.0f;
|
||||||
viewport.y = 0.0f;
|
viewport.y = 0.0f;
|
||||||
viewport.width = static_cast<float>(m_swapchainExtent.width);
|
viewport.width = static_cast<float>(swapchainExtent.width);
|
||||||
viewport.height = static_cast<float>(m_swapchainExtent.height);
|
viewport.height = static_cast<float>(swapchainExtent.height);
|
||||||
viewport.minDepth = 0.0f;
|
viewport.minDepth = 0.0f;
|
||||||
viewport.maxDepth = 1.0f;
|
viewport.maxDepth = 1.0f;
|
||||||
vkCmdSetViewport(m_commandBuffers[m_currentFrameIndex], 0, 1, &viewport);
|
vkCmdSetViewport(m_commandBuffers[m_currentFrameIndex], 0, 1, &viewport);
|
||||||
|
|
||||||
VkRect2D scissor{};
|
VkRect2D scissor{};
|
||||||
scissor.offset = {0, 0};
|
scissor.offset = {0, 0};
|
||||||
scissor.extent = m_swapchainExtent;
|
scissor.extent = swapchainExtent;
|
||||||
vkCmdSetScissor(m_commandBuffers[m_currentFrameIndex], 0, 1, &scissor);
|
vkCmdSetScissor(m_commandBuffers[m_currentFrameIndex], 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdDraw(m_commandBuffers[m_currentFrameIndex], 3, 1, 0, 0);
|
vkCmdDraw(m_commandBuffers[m_currentFrameIndex], 3, 1, 0, 0);
|
||||||
@@ -369,12 +371,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::Present() {
|
void VulkanRenderer::Present() {
|
||||||
MOBILEGL_ASSERT(m_imageIndexAcquired < m_swapchainImages.size(), "Present, acquired image index out of range");
|
MOBILEGL_ASSERT(m_imageIndexAcquired < m_swapchainObject.GetImageCount(),
|
||||||
|
"Present, acquired image index out of range");
|
||||||
const Bool hasRecordedWork = m_hasCommandBufferRecorded[m_currentFrameIndex];
|
const Bool hasRecordedWork = m_hasCommandBufferRecorded[m_currentFrameIndex];
|
||||||
Bool needsLayoutTransitionForPresent = false;
|
Bool needsLayoutTransitionForPresent = false;
|
||||||
|
|
||||||
if (!hasRecordedWork) {
|
if (!hasRecordedWork) {
|
||||||
auto& acquiredImageLayout = m_swapchainImageLayouts[m_imageIndexAcquired];
|
const auto acquiredImageLayout = m_swapchainObject.GetImageLayout(m_imageIndexAcquired);
|
||||||
if (acquiredImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR &&
|
if (acquiredImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR &&
|
||||||
acquiredImageLayout != VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR) {
|
acquiredImageLayout != VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR) {
|
||||||
needsLayoutTransitionForPresent = true;
|
needsLayoutTransitionForPresent = true;
|
||||||
@@ -395,7 +398,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
presentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
presentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
presentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
presentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
presentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
presentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
presentBarrier.image = m_swapchainImages[m_imageIndexAcquired];
|
presentBarrier.image = m_swapchainObject.GetImage(m_imageIndexAcquired);
|
||||||
presentBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
presentBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
presentBarrier.subresourceRange.baseMipLevel = 0;
|
presentBarrier.subresourceRange.baseMipLevel = 0;
|
||||||
presentBarrier.subresourceRange.levelCount = 1;
|
presentBarrier.subresourceRange.levelCount = 1;
|
||||||
@@ -427,14 +430,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||||
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, m_imageInFlightFences[m_currentFrameIndex]));
|
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, m_imageInFlightFences[m_currentFrameIndex]));
|
||||||
m_hasCommandBufferRecorded[m_currentFrameIndex] = false;
|
m_hasCommandBufferRecorded[m_currentFrameIndex] = false;
|
||||||
m_swapchainImageLayouts[m_imageIndexAcquired] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
|
|
||||||
// 2) Present current frame.
|
// 2) Present current frame.
|
||||||
VkPresentInfoKHR presentInfo{};
|
VkPresentInfoKHR presentInfo{};
|
||||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
presentInfo.waitSemaphoreCount = 1;
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
presentInfo.pWaitSemaphores = signalSemaphores;
|
presentInfo.pWaitSemaphores = signalSemaphores;
|
||||||
VkSwapchainKHR swapChains[] = {m_swapchain};
|
VkSwapchainKHR swapChains[] = {m_swapchainObject.GetHandle()};
|
||||||
presentInfo.swapchainCount = 1;
|
presentInfo.swapchainCount = 1;
|
||||||
presentInfo.pSwapchains = swapChains;
|
presentInfo.pSwapchains = swapChains;
|
||||||
presentInfo.pImageIndices = &m_imageIndexAcquired;
|
presentInfo.pImageIndices = &m_imageIndexAcquired;
|
||||||
@@ -455,8 +458,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
"Present, vkWaitForFences");
|
"Present, vkWaitForFences");
|
||||||
VK_VERIFY(vkResetFences(m_device, 1, &m_imageInFlightFences[m_currentFrameIndex]), "Present, vkResetFences");
|
VK_VERIFY(vkResetFences(m_device, 1, &m_imageInFlightFences[m_currentFrameIndex]), "Present, vkResetFences");
|
||||||
result =
|
result =
|
||||||
vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_imageAvailableSemaphores[m_currentFrameIndex],
|
vkAcquireNextImageKHR(m_device, m_swapchainObject.GetHandle(), UINT64_MAX,
|
||||||
VK_NULL_HANDLE, &m_imageIndexAcquired);
|
m_imageAvailableSemaphores[m_currentFrameIndex], VK_NULL_HANDLE,
|
||||||
|
&m_imageIndexAcquired);
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
||||||
MGLOG_D("Present, vkAcquireNextImageKHR got %d, recreating swapchain", result);
|
MGLOG_D("Present, vkAcquireNextImageKHR got %d, recreating swapchain", result);
|
||||||
RecreateSwapchain();
|
RecreateSwapchain();
|
||||||
@@ -644,8 +648,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check swapchain capabilities
|
// Check swapchain capabilities
|
||||||
newDevice.swapchainCapabilities = GetSwapchainCapabilities(newVkDevice, surface);
|
auto swapchainCapabilities = SwapchainObject::GetSwapchainCapabilities(newVkDevice, surface);
|
||||||
if (!newDevice.swapchainCapabilities.IsComplete()) {
|
if (!swapchainCapabilities.IsComplete()) {
|
||||||
outBetterDevice = otherDevice;
|
outBetterDevice = otherDevice;
|
||||||
MGLOG_I(" Ignored physical device. (Reason: Swapchain capabilities not met)");
|
MGLOG_I(" Ignored physical device. (Reason: Swapchain capabilities not met)");
|
||||||
return false;
|
return false;
|
||||||
@@ -695,32 +699,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSurfaceFormatKHR VulkanRenderer::ChooseSwapchainSurfaceFormat(
|
|
||||||
const Vector<VkSurfaceFormatKHR>& availableFormats) {
|
|
||||||
for (const auto& availableFormat : availableFormats) {
|
|
||||||
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB &&
|
|
||||||
availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
|
||||||
return availableFormat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Properly rank other formats
|
|
||||||
return availableFormats[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
VkPresentModeKHR VulkanRenderer::ChooseSwapchainPresentMode(const Vector<VkPresentModeKHR>& availablePresentModes) {
|
|
||||||
for (auto desiredPresentMode : s_desiredPresentModes) {
|
|
||||||
for (const auto& presentMode : availablePresentModes) {
|
|
||||||
if (presentMode == desiredPresentMode) {
|
|
||||||
return presentMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Properly rank other modes
|
|
||||||
return availablePresentModes[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool VulkanRenderer::IsNecessaryDeviceExtensionSupported(VkPhysicalDevice device) {
|
Bool VulkanRenderer::IsNecessaryDeviceExtensionSupported(VkPhysicalDevice device) {
|
||||||
Uint32 extensionCount = 0;
|
Uint32 extensionCount = 0;
|
||||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
|
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
|
||||||
@@ -751,32 +729,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanRenderer::SwapchainCapabilities VulkanRenderer::GetSwapchainCapabilities(VkPhysicalDevice device,
|
|
||||||
VkSurfaceKHR surface) {
|
|
||||||
SwapchainCapabilities swapchainCapabilities;
|
|
||||||
|
|
||||||
VK_VERIFY(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &swapchainCapabilities.capabilities));
|
|
||||||
Uint32 formatCount;
|
|
||||||
VK_VERIFY(vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr));
|
|
||||||
|
|
||||||
if (formatCount != 0) {
|
|
||||||
swapchainCapabilities.surfaceFormats.resize(formatCount);
|
|
||||||
VK_VERIFY(vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount,
|
|
||||||
swapchainCapabilities.surfaceFormats.data()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint32 presentModeCount;
|
|
||||||
VK_VERIFY(vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr));
|
|
||||||
|
|
||||||
if (presentModeCount != 0) {
|
|
||||||
swapchainCapabilities.presentModes.resize(presentModeCount);
|
|
||||||
VK_VERIFY(vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount,
|
|
||||||
swapchainCapabilities.presentModes.data()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return swapchainCapabilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::CreateLogicalDeviceAndQueues() {
|
void VulkanRenderer::CreateLogicalDeviceAndQueues() {
|
||||||
Float queuePriority = 1.0f;
|
Float queuePriority = 1.0f;
|
||||||
|
|
||||||
@@ -1154,35 +1106,35 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
m_physicalDevice.swapchainCapabilities = GetSwapchainCapabilities(m_physicalDevice.handle, m_surface);
|
const auto swapchainCapabilities = SwapchainObject::GetSwapchainCapabilities(m_physicalDevice.handle, m_surface);
|
||||||
|
|
||||||
auto& supportedSurfaceFormats = m_physicalDevice.swapchainCapabilities.surfaceFormats;
|
auto& supportedSurfaceFormats = swapchainCapabilities.surfaceFormats;
|
||||||
MGLOG_I("Got %d surface formats: ", supportedSurfaceFormats.size());
|
MGLOG_I("Got %d surface formats: ", supportedSurfaceFormats.size());
|
||||||
for (auto& surfaceFormat : supportedSurfaceFormats) {
|
for (auto& surfaceFormat : supportedSurfaceFormats) {
|
||||||
MGLOG_I(" [%s, %s]", surfaceFormatToStr(surfaceFormat.format),
|
MGLOG_I(" [%s, %s]", surfaceFormatToStr(surfaceFormat.format),
|
||||||
colorSpaceToStr(surfaceFormat.colorSpace));
|
colorSpaceToStr(surfaceFormat.colorSpace));
|
||||||
}
|
}
|
||||||
m_swapchainSurfaceFormat = ChooseSwapchainSurfaceFormat(supportedSurfaceFormats);
|
const auto pickedSurfaceFormat = SwapchainObject::ChooseSwapchainSurfaceFormat(supportedSurfaceFormats);
|
||||||
MGLOG_I("Picked surface format: [%s, %s]", surfaceFormatToStr(m_swapchainSurfaceFormat.format),
|
MGLOG_I("Picked surface format: [%s, %s]", surfaceFormatToStr(pickedSurfaceFormat.format),
|
||||||
colorSpaceToStr(m_swapchainSurfaceFormat.colorSpace));
|
colorSpaceToStr(pickedSurfaceFormat.colorSpace));
|
||||||
|
|
||||||
auto& supportedPresentModes = m_physicalDevice.swapchainCapabilities.presentModes;
|
auto& supportedPresentModes = swapchainCapabilities.presentModes;
|
||||||
MGLOG_I("Got %d present mode: ", supportedPresentModes.size());
|
MGLOG_I("Got %d present mode: ", supportedPresentModes.size());
|
||||||
for (auto& presentMode : supportedPresentModes) {
|
for (auto& presentMode : supportedPresentModes) {
|
||||||
MGLOG_I(" %s", presentModeToStr(presentMode));
|
MGLOG_I(" %s", presentModeToStr(presentMode));
|
||||||
}
|
}
|
||||||
auto presentMode = ChooseSwapchainPresentMode(supportedPresentModes);
|
auto presentMode = SwapchainObject::ChooseSwapchainPresentMode(supportedPresentModes);
|
||||||
MGLOG_I("Picked present mode: %s", presentModeToStr(presentMode));
|
MGLOG_I("Picked present mode: %s", presentModeToStr(presentMode));
|
||||||
|
|
||||||
const auto& swapchainCaps = m_physicalDevice.swapchainCapabilities.capabilities;
|
const auto& swapchainCaps = swapchainCapabilities.capabilities;
|
||||||
auto imageCount = std::max<uint32_t>(m_config.MaxFramesInFlight, swapchainCaps.minImageCount);
|
auto imageCount = std::max<uint32_t>(m_config.MaxFramesInFlight, swapchainCaps.minImageCount);
|
||||||
MGLOG_I("Set minImageCount = %u", imageCount);
|
MGLOG_I("Set minImageCount = %u", imageCount);
|
||||||
|
|
||||||
VkSwapchainCreateInfoKHR sci{VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
|
VkSwapchainCreateInfoKHR sci{VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
|
||||||
sci.surface = m_surface;
|
sci.surface = m_surface;
|
||||||
sci.minImageCount = imageCount;
|
sci.minImageCount = imageCount;
|
||||||
sci.imageFormat = m_swapchainSurfaceFormat.format;
|
sci.imageFormat = pickedSurfaceFormat.format;
|
||||||
sci.imageColorSpace = m_swapchainSurfaceFormat.colorSpace;
|
sci.imageColorSpace = pickedSurfaceFormat.colorSpace;
|
||||||
sci.imageExtent = swapchainCaps.currentExtent;
|
sci.imageExtent = swapchainCaps.currentExtent;
|
||||||
sci.imageArrayLayers = 1;
|
sci.imageArrayLayers = 1;
|
||||||
sci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
sci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
@@ -1204,39 +1156,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
sci.presentMode = presentMode;
|
sci.presentMode = presentMode;
|
||||||
sci.clipped = VK_TRUE;
|
sci.clipped = VK_TRUE;
|
||||||
sci.oldSwapchain = VK_NULL_HANDLE;
|
sci.oldSwapchain = VK_NULL_HANDLE;
|
||||||
VK_VERIFY(vkCreateSwapchainKHR(m_device, &sci, nullptr, &m_swapchain));
|
m_swapchainObject.Create(m_device, sci);
|
||||||
|
|
||||||
Uint32 gotImageCount = 0;
|
|
||||||
VK_VERIFY(vkGetSwapchainImagesKHR(m_device, m_swapchain, &gotImageCount, nullptr));
|
|
||||||
m_swapchainImages.resize(gotImageCount, VK_NULL_HANDLE);
|
|
||||||
VK_VERIFY(vkGetSwapchainImagesKHR(m_device, m_swapchain, &gotImageCount, m_swapchainImages.data()));
|
|
||||||
m_swapchainImageLayouts.assign(gotImageCount, VK_IMAGE_LAYOUT_UNDEFINED);
|
|
||||||
m_swapchainExtent = swapchainCaps.currentExtent;
|
|
||||||
|
|
||||||
MGLOG_I("Swapchain created, extent = %dx%d, swapchain imageCount = %d", m_swapchainExtent.width,
|
|
||||||
m_swapchainExtent.height, gotImageCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::CreateSwapchainImageViews() {
|
|
||||||
m_swapchainImageViews.resize(m_swapchainImages.size(), VK_NULL_HANDLE);
|
|
||||||
for (size_t i = 0; i < m_swapchainImageViews.size(); i++) {
|
|
||||||
VkImageViewCreateInfo createInfo{};
|
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
||||||
createInfo.image = m_swapchainImages[i];
|
|
||||||
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
||||||
createInfo.format = m_swapchainSurfaceFormat.format;
|
|
||||||
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
||||||
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
||||||
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
||||||
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
||||||
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
createInfo.subresourceRange.baseMipLevel = 0;
|
|
||||||
createInfo.subresourceRange.levelCount = 1;
|
|
||||||
createInfo.subresourceRange.baseArrayLayer = 0;
|
|
||||||
createInfo.subresourceRange.layerCount = 1;
|
|
||||||
VK_VERIFY(vkCreateImageView(m_device, &createInfo, nullptr, &m_swapchainImageViews[i]));
|
|
||||||
}
|
|
||||||
MGLOG_I("Swapchain image views created");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateCommandPool() {
|
void VulkanRenderer::CreateCommandPool() {
|
||||||
@@ -1260,7 +1180,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
void VulkanRenderer::CreateDefaultRenderPass() {
|
void VulkanRenderer::CreateDefaultRenderPass() {
|
||||||
VkAttachmentDescription color{};
|
VkAttachmentDescription color{};
|
||||||
color.format = m_swapchainSurfaceFormat.format;
|
color.format = m_swapchainObject.GetSurfaceFormat().format;
|
||||||
color.samples = VK_SAMPLE_COUNT_1_BIT;
|
color.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
color.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
color.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
color.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
color.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
@@ -1286,7 +1206,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
void VulkanRenderer::CreateDefaultFramebuffers() {
|
void VulkanRenderer::CreateDefaultFramebuffers() {
|
||||||
// Create framebuffers now (use swapchain imageviews)
|
// Create framebuffers now (use swapchain imageviews)
|
||||||
const auto& imageViews = m_swapchainImageViews;
|
const auto& imageViews = m_swapchainObject.GetImageViews();
|
||||||
|
const auto swapchainExtent = m_swapchainObject.GetExtent();
|
||||||
Vector<VkFramebuffer>& fbs = m_framebuffers;
|
Vector<VkFramebuffer>& fbs = m_framebuffers;
|
||||||
fbs.reserve(imageViews.size());
|
fbs.reserve(imageViews.size());
|
||||||
for (auto iv : imageViews) {
|
for (auto iv : imageViews) {
|
||||||
@@ -1295,8 +1216,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
fbci.renderPass = m_renderPass;
|
fbci.renderPass = m_renderPass;
|
||||||
fbci.attachmentCount = 1;
|
fbci.attachmentCount = 1;
|
||||||
fbci.pAttachments = attachments;
|
fbci.pAttachments = attachments;
|
||||||
fbci.width = m_swapchainExtent.width;
|
fbci.width = swapchainExtent.width;
|
||||||
fbci.height = m_swapchainExtent.height;
|
fbci.height = swapchainExtent.height;
|
||||||
fbci.layers = 1;
|
fbci.layers = 1;
|
||||||
VkFramebuffer fb;
|
VkFramebuffer fb;
|
||||||
VK_VERIFY(vkCreateFramebuffer(m_device, &fbci, nullptr, &fb), "vkCreateFramebuffer");
|
VK_VERIFY(vkCreateFramebuffer(m_device, &fbci, nullptr, &fb), "vkCreateFramebuffer");
|
||||||
@@ -1406,24 +1327,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_renderPass = VK_NULL_HANDLE;
|
m_renderPass = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto imageView : m_swapchainImageViews) {
|
m_swapchainObject.Shutdown(m_device);
|
||||||
vkDestroyImageView(m_device, imageView, nullptr);
|
|
||||||
}
|
|
||||||
m_swapchainImageViews.clear();
|
|
||||||
|
|
||||||
if (m_swapchain != VK_NULL_HANDLE) {
|
|
||||||
vkDestroySwapchainKHR(m_device, m_swapchain, nullptr);
|
|
||||||
m_swapchain = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
m_swapchainImages.clear();
|
|
||||||
m_swapchainImageLayouts.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::RecreateSwapchain() {
|
void VulkanRenderer::RecreateSwapchain() {
|
||||||
// Handle cases like minimize on Windows, where swapchain could return a 0x0 extent
|
// Handle cases like minimize on Windows, where swapchain could return a 0x0 extent
|
||||||
m_physicalDevice.swapchainCapabilities = GetSwapchainCapabilities(m_physicalDevice.handle, m_surface);
|
const auto swapchainCapabilities = SwapchainObject::GetSwapchainCapabilities(m_physicalDevice.handle, m_surface);
|
||||||
if (m_physicalDevice.swapchainCapabilities.capabilities.currentExtent.width == 0 ||
|
if (swapchainCapabilities.capabilities.currentExtent.width == 0 ||
|
||||||
m_physicalDevice.swapchainCapabilities.capabilities.currentExtent.height == 0) {
|
swapchainCapabilities.capabilities.currentExtent.height == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1432,7 +1343,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
ShutdownSwapchain();
|
ShutdownSwapchain();
|
||||||
|
|
||||||
CreateSwapchain();
|
CreateSwapchain();
|
||||||
CreateSwapchainImageViews();
|
|
||||||
CreateDefaultRenderPass();
|
CreateDefaultRenderPass();
|
||||||
CreateDefaultFramebuffers();
|
CreateDefaultFramebuffers();
|
||||||
std::fill(m_hasCommandBufferRecorded.begin(), m_hasCommandBufferRecorded.end(), false);
|
std::fill(m_hasCommandBufferRecorded.begin(), m_hasCommandBufferRecorded.end(), false);
|
||||||
|
|||||||
@@ -8,15 +8,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "SwapchainObject.h"
|
||||||
#include <Includes.h>
|
#include <Includes.h>
|
||||||
|
|
||||||
#define VK_VERIFY(expr, ...) \
|
#include "../VkIncludes.h"
|
||||||
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)
|
|
||||||
|
|
||||||
#define ENUM_STR_CASE(c) case c: return #c;
|
|
||||||
|
|
||||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
using RenderCallback = std::function<void(VkCommandBuffer cmdBuf, uint32_t imageIndex, VkExtent2D extent)>;
|
using RenderCallback = std::function<void(VkCommandBuffer cmdBuf, uint32_t imageIndex, VkExtent2D extent)>;
|
||||||
@@ -48,20 +43,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Int32 presentFamily = -1;
|
Int32 presentFamily = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SwapchainCapabilities {
|
|
||||||
VkSurfaceCapabilitiesKHR capabilities;
|
|
||||||
Vector<VkSurfaceFormatKHR> surfaceFormats;
|
|
||||||
Vector<VkPresentModeKHR> presentModes;
|
|
||||||
|
|
||||||
Bool IsComplete() const {
|
|
||||||
return !surfaceFormats.empty() && !presentModes.empty();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PhysicalDevice {
|
struct PhysicalDevice {
|
||||||
QueueFamilyIndices queueFamilies;
|
QueueFamilyIndices queueFamilies;
|
||||||
VkPhysicalDeviceProperties properties;
|
VkPhysicalDeviceProperties properties;
|
||||||
SwapchainCapabilities swapchainCapabilities;
|
|
||||||
VkPhysicalDevice handle = VK_NULL_HANDLE;
|
VkPhysicalDevice handle = VK_NULL_HANDLE;
|
||||||
|
|
||||||
Bool IsComplete() const {
|
Bool IsComplete() const {
|
||||||
@@ -83,12 +67,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
// VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
// VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||||
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
SwapchainObject m_swapchainObject;
|
||||||
VkSurfaceFormatKHR m_swapchainSurfaceFormat;
|
|
||||||
Vector<VkImage> m_swapchainImages;
|
|
||||||
Vector<VkImageLayout> m_swapchainImageLayouts;
|
|
||||||
VkExtent2D m_swapchainExtent;
|
|
||||||
Vector<VkImageView> m_swapchainImageViews;
|
|
||||||
|
|
||||||
// Vector<VkQueueFamilyProperties> m_queueFamilies;
|
// Vector<VkQueueFamilyProperties> m_queueFamilies;
|
||||||
// QueueFamilyIndices m_queueFamilyIndices;
|
// QueueFamilyIndices m_queueFamilyIndices;
|
||||||
@@ -120,7 +99,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void PickPhysicalDevice();
|
void PickPhysicalDevice();
|
||||||
void CreateLogicalDeviceAndQueues();
|
void CreateLogicalDeviceAndQueues();
|
||||||
void CreateSwapchain();
|
void CreateSwapchain();
|
||||||
void CreateSwapchainImageViews();
|
|
||||||
void CreateCommandPool();
|
void CreateCommandPool();
|
||||||
void CreateCommandBuffers();
|
void CreateCommandBuffers();
|
||||||
void CreateDefaultRenderPass();
|
void CreateDefaultRenderPass();
|
||||||
@@ -137,20 +115,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
static Int GetQueueFamilyIndex(const Vector<VkQueueFamilyProperties>& queueFamilies, VkQueueFlagBits flag);
|
static Int GetQueueFamilyIndex(const Vector<VkQueueFamilyProperties>& queueFamilies, VkQueueFlagBits flag);
|
||||||
static Vector<VkExtensionProperties> EnumerateInstanceExtensions();
|
static Vector<VkExtensionProperties> EnumerateInstanceExtensions();
|
||||||
static Bool IsNecessaryDeviceExtensionSupported(VkPhysicalDevice device);
|
static Bool IsNecessaryDeviceExtensionSupported(VkPhysicalDevice device);
|
||||||
static SwapchainCapabilities GetSwapchainCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface);
|
|
||||||
static Bool GetMoreCapablePhysicalDevice(VkPhysicalDevice newVkDevice, VkSurfaceKHR surface, const PhysicalDevice& compareWithDevice, PhysicalDevice& outBetterDevice);
|
static Bool GetMoreCapablePhysicalDevice(VkPhysicalDevice newVkDevice, VkSurfaceKHR surface, const PhysicalDevice& compareWithDevice, PhysicalDevice& outBetterDevice);
|
||||||
static VkSurfaceFormatKHR ChooseSwapchainSurfaceFormat(const Vector<VkSurfaceFormatKHR>& availableFormats);
|
|
||||||
static VkPresentModeKHR ChooseSwapchainPresentMode(const Vector<VkPresentModeKHR>& availablePresentModes);
|
|
||||||
static constexpr VkDynamicState s_dynamicStates[] = {
|
static constexpr VkDynamicState s_dynamicStates[] = {
|
||||||
VK_DYNAMIC_STATE_VIEWPORT,
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
VK_DYNAMIC_STATE_SCISSOR
|
VK_DYNAMIC_STATE_SCISSOR
|
||||||
};
|
};
|
||||||
static constexpr VkPresentModeKHR s_desiredPresentModes[] {
|
|
||||||
VK_PRESENT_MODE_MAILBOX_KHR,
|
|
||||||
VK_PRESENT_MODE_IMMEDIATE_KHR,
|
|
||||||
VK_PRESENT_MODE_FIFO_RELAXED_KHR,
|
|
||||||
VK_PRESENT_MODE_FIFO_KHR
|
|
||||||
};
|
|
||||||
static constexpr const char* s_validationLayerNames[] = {
|
static constexpr const char* s_validationLayerNames[] = {
|
||||||
"VK_LAYER_KHRONOS_validation"
|
"VK_LAYER_KHRONOS_validation"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// MobileGL - MobileGL/MG_Backend/DirectVulkan/VkIncludes.h
|
||||||
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||||
|
// Licensed under the GNU Lesser General Public License v3.0:
|
||||||
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
// End of Source File Header
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
|
#define ENUM_STR_CASE(c) case c: return #c;
|
||||||
Reference in New Issue
Block a user