[Feat] (MG_Backend/DirectVulkan|MG_Util): Get Vulkan device info.

This commit is contained in:
BZLZHH
2026-02-20 16:21:28 +08:00
parent 99c1697fba
commit 39eb6a9026
12 changed files with 2929 additions and 2853 deletions
+1
View File
@@ -168,6 +168,7 @@ set(SOURCE_FILES
MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.cpp MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.cpp
MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp
MobileGL/MG_Util/BackendLoaders/Vulkan/Loader.cpp
MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp
MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp
@@ -9,8 +9,8 @@
#include "BackendObject_DirectVulkan.h" #include "BackendObject_DirectVulkan.h"
#include "MG_Backend/BackendObject.h" #include "MG_Backend/BackendObject.h"
#include <MG_Backend/DirectVulkan/DirectVulkan.h> #include <MG_Backend/DirectVulkan/DirectVulkan.h>
#include <MG_Backend/DirectVulkan/TmpImpl.h>
#include <MG_Util/BackendLoaders/OpenGL/Loader.h> #include <MG_Util/BackendLoaders/OpenGL/Loader.h>
#include <format>
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
BackendObject_DirectVulkan::~BackendObject_DirectVulkan() = default; BackendObject_DirectVulkan::~BackendObject_DirectVulkan() = default;
@@ -24,7 +24,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void BackendObject_DirectVulkan::Initialize() { void BackendObject_DirectVulkan::Initialize() {
m_initialized = true; m_initialized = true;
// TODO }
void BackendObject_DirectVulkan::InitCapabilities() {
if (!m_initialized) {
MGLOG_E("Cannot initialize capabilities before backend is initialized");
return;
}
MG_Util::BackendLoader::QueryVulkanCapabilities(m_vulkanCaps,
DirectVulkan::GetVulkanState().ctx->GetPhysicalDevice());
UpdateDynamicBackendParameters(); UpdateDynamicBackendParameters();
} }
@@ -53,7 +62,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// Format: // Format:
// <GPU Name>, Vulkan <Vulkan Version>, Driver <Driver Version> // <GPU Name>, Vulkan <Vulkan Version>, Driver <Driver Version>
// TODO // TODO
return "Vulkan"; String str = m_vulkanCaps.DeviceName + ", Vulkan " + m_vulkanCaps.VulkanAPIVersion.toString() + ", Driver " +
m_vulkanCaps.DriverVersionString;
return str;
} }
BackendType BackendObject_DirectVulkan::GetBackendType() const { BackendType BackendObject_DirectVulkan::GetBackendType() const {
@@ -103,6 +114,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
void BackendObject_DirectVulkan::UpdateDynamicBackendParameters() { void BackendObject_DirectVulkan::UpdateDynamicBackendParameters() {
m_dynamicParameters.UniformBufferOffsetAlignment = 256; // TODO m_dynamicParameters.UniformBufferOffsetAlignment = m_vulkanCaps.UniformBufferOffsetAlignment;
} }
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -9,13 +9,16 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
#include "../BackendObject.h" #include "../BackendObject.h"
#include <MG_Util/BackendLoaders/Vulkan/Loader.h>
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
class BackendObject_DirectVulkan : public BackendObject { class BackendObject_DirectVulkan : public BackendObject {
public: public:
~BackendObject_DirectVulkan() override; ~BackendObject_DirectVulkan() override;
void Initialize() override; void Initialize() override;
void InitWindowSurface() override; void InitWindowSurface() override;
void InitCapabilities() override;
const RendererInfo& GetRendererInfo() const override; const RendererInfo& GetRendererInfo() const override;
String GetBackendAPIVersionString() const override; String GetBackendAPIVersionString() const override;
@@ -28,5 +31,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool m_initialized = false; Bool m_initialized = false;
DynamicBackendParameters m_dynamicParameters; DynamicBackendParameters m_dynamicParameters;
MG_External::VulkanCapabilities m_vulkanCaps;
}; };
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -67,4 +67,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void Present() { void Present() {
TmpImpl::Present(); TmpImpl::Present();
} }
const TmpImpl::VulkanState& GetVulkanState() {
return TmpImpl::GetVulkanState();
}
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -11,6 +11,10 @@
#include "Renderer/VulkanRenderer.h" #include "Renderer/VulkanRenderer.h"
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
namespace TmpImpl {
class VulkanState;
} // namespace TmpImpl
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value); void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value); void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
@@ -51,4 +55,5 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels); void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
Bool InitWindowSurface(NativeWindowType window); Bool InitWindowSurface(NativeWindowType window);
void Present(); void Present();
const TmpImpl::VulkanState& GetVulkanState();
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
+40 -280
View File
@@ -8,13 +8,6 @@
#include "TmpImpl.h" #include "TmpImpl.h"
#include "MG_Backend/DirectVulkan/DirectVulkan.h" #include "MG_Backend/DirectVulkan/DirectVulkan.h"
#include "MG_Util/Types.h"
#include "Renderer/VkCommon.h"
#include "Renderer/VulkanContext.h"
#include "Renderer/SwapchainManager.h"
#include "Renderer/FrameContext.h"
#include "Managers/ProgramManager.h"
#include <MG_State/GLState/Core.h>
#include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h> #include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h>
#include <MG_Util/ShaderTranspiler/Types.h> #include <MG_Util/ShaderTranspiler/Types.h>
#include "MG_Util/Debug/Log.h" #include "MG_Util/Debug/Log.h"
@@ -22,222 +15,10 @@
#define DEBUG_TRACE_POINT() MGLOG_D("DV TmpImpl Trace: %s:%d", __func__, __LINE__) #define DEBUG_TRACE_POINT() MGLOG_D("DV TmpImpl Trace: %s:%d", __func__, __LINE__)
namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl { namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
namespace {
class PendingClearInfo; class PendingClearInfo;
void BeginRenderPass(GLbitfield clearMask, const PendingClearInfo* clearInfo); void BeginRenderPass(GLbitfield clearMask, const PendingClearInfo* clearInfo);
namespace DV = MobileGL::MG_Backend::DirectVulkan::VkManager;
using BufferObject = MobileGL::MG_State::GLState::BufferObject;
using ProgramObject = MobileGL::MG_State::GLState::ProgramObject;
using VertexArrayObject = MobileGL::MG_State::GLState::VertexArrayObject;
using FramebufferObject = MobileGL::MG_State::GLState::FramebufferObject;
using FramebufferAttachmentObject = MobileGL::MG_State::GLState::FramebufferAttachmentObject;
using ITextureObject = MobileGL::MG_State::GLState::ITextureObject;
using RenderbufferObject = MobileGL::MG_State::GLState::RenderbufferObject;
using SamplerObject = MobileGL::MG_State::GLState::SamplerObject;
using TextureObjectMipmap = MobileGL::MG_State::GLState::TextureObjectMipmap;
using TrashImage = MobileGL::MG_Backend::DirectVulkan::TrashImage;
struct BufferResource { VulkanState g;
VkBuffer buffer = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
VkDeviceSize size = 0;
VkBufferUsageFlags usage = 0;
VkMemoryPropertyFlags props = 0;
void* mapped = nullptr;
Uint32 lastUsedFrame = ~0u;
};
struct TextureResource {
VkImage image = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
UnorderedMap<Uint32, VkImageView> mipViews;
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent3D extent{0, 0, 1};
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
Uint32 mipLevels = 1;
Uint16 paramsVersion = 0;
bool valid = false;
};
struct RenderbufferResource {
VkImage image = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent2D extent{0, 0};
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
bool valid = false;
};
struct SamplerResource {
VkSampler sampler = VK_NULL_HANDLE;
Uint16 version = 0;
SamplerParameters params{};
};
struct PendingClearInfo {
GLbitfield mask = 0;
FloatVec4 clearColor = {0.0f, 0.0f, 0.0f, 1.0f};
Float clearDepth = 1.0f;
};
struct UniformBindingInfo {
String name;
Uint32 binding = 0;
Uint32 set = 0;
Uint32 blockIndex = 0xFFFFFFFFu;
VkShaderStageFlags stages = 0;
};
struct SamplerBindingInfo {
String name;
Uint32 binding = 0;
Uint32 set = 0;
VkShaderStageFlags stages = 0;
};
struct ProgramResource {
ProgramObject* program = nullptr;
Uint64 spvHash = 0;
DV::ProgramManager::HashType programHash = 0;
Vector<VkPipelineShaderStageCreateInfo>* shaderStages = nullptr;
VkDescriptorSetLayout setLayout = VK_NULL_HANDLE;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
struct UboPool {
Vector<BufferResource> buffers;
Uint32 cursor = 0;
};
Vector<UboPool> uboPools;
SizeT uboSize = 0;
Int32 uboBinding = -1;
Uint32 uniformDescriptorCount = 0;
Uint32 samplerDescriptorCount = 0;
Vector<UniformBindingInfo> uniformBindings;
Vector<SamplerBindingInfo> samplerBindings;
UnorderedMap<String, Uint32> samplerBindingByName;
UnorderedMap<Uint64, VkPipeline> pipelines;
};
struct DescriptorPoolConfig {
Uint32 maxSets = 0;
Uint32 uniformCount = 0;
Uint32 samplerCount = 0;
};
struct FrameDescriptorPools {
Vector<VkDescriptorPool> pools;
DescriptorPoolConfig config;
Uint32 activePool = 0;
};
struct VertexAttribKey {
Uint8 enabled = 0;
Uint8 size = 0;
Uint8 type = 0;
Uint8 normalized = 0;
Uint8 isInteger = 0;
Uint8 divisor = 0;
Uint16 pad = 0;
Uint32 stride = 0;
Uint64 offset = 0;
};
struct AttachmentInfo {
FramebufferAttachmentType type = FramebufferAttachmentType::None;
VkImageView view = VK_NULL_HANDLE;
VkFormat format = VK_FORMAT_UNDEFINED;
VkImageAspectFlags aspect = 0;
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ITextureObject* texture = nullptr;
RenderbufferObject* renderbuffer = nullptr;
};
struct BackendFramebufferObject {
Array<VkRenderPass, 8> renderPasses = {};
VkFramebuffer framebuffer = VK_NULL_HANDLE;
VkExtent2D extent{0, 0};
Uint32 colorAttachmentCount = 0;
Bool hasDepth = false;
VkFormat depthFormat = VK_FORMAT_UNDEFINED;
Uint64 renderPassCompatHash = 0;
Vector<AttachmentInfo> attachments;
Array<Int32, static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>
attachmentIndex = {};
FramebufferObject::FramebufferAttachmentVersionArray syncedAttachmentVersions = {0};
FramebufferObject::FramebufferAttachmentArray frontendDrawBuffers = {FramebufferAttachmentType::None};
Array<Int32, FramebufferObject::MAX_DRAW_BUFFERS> drawBufferAttachmentIndices = {};
FramebufferAttachmentType frontendReadBuffer = FramebufferAttachmentType::Color0;
Uint64 configHash = 0;
Uint16 objectVersion = 0;
Bool IsValid() const { return renderPasses[0] != VK_NULL_HANDLE && framebuffer != VK_NULL_HANDLE; }
};
struct BackendState {
UniquePtr<DV::VulkanContext> ctx;
UniquePtr<DV::SwapchainManager> swapchain;
UniquePtr<DV::ProgramManager> programMgr;
Array<VkRenderPass, 8> renderPasses = {};
VkCommandPool commandPool = VK_NULL_HANDLE;
Vector<UniquePtr<DV::FrameContext>> frames;
Vector<FrameDescriptorPools> frameDescriptorPools;
Uint32 currentFrame = 0;
Uint32 maxFramesInFlight = 2;
Bool initialized = false;
UintVec2 viewportSize{0, 0};
VkImage depthImage = VK_NULL_HANDLE;
VkDeviceMemory depthMemory = VK_NULL_HANDLE;
VkImageView depthView = VK_NULL_HANDLE;
VkFormat depthFormat = VK_FORMAT_UNDEFINED;
Uint64 defaultRenderPassCompatHash = 0;
BufferResource nullUbo;
TextureResource defaultTexture;
SamplerResource defaultSampler;
UnorderedMap<const BufferObject*, BufferResource> buffers;
UnorderedMap<const ITextureObject*, TextureResource> textures;
UnorderedMap<const RenderbufferObject*, RenderbufferResource> renderbuffers;
UnorderedMap<const SamplerObject*, SamplerResource> samplers;
UnorderedMap<const ProgramObject*, ProgramResource> programs;
UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>>
framebuffers;
VkRenderPass activeRenderPass = VK_NULL_HANDLE;
VkFramebuffer activeFramebuffer = VK_NULL_HANDLE;
VkExtent2D activeExtent{0, 0};
Uint32 activeColorAttachmentCount = 1;
Bool activeHasDepth = false;
VkFormat activeDepthFormat = VK_FORMAT_UNDEFINED;
SharedPtr<MG_State::GLState::FramebufferObject> activeStateFBO = nullptr;
SharedPtr<BackendFramebufferObject> activeBackendFBO = nullptr;
Bool activeIsDefault = true;
Bool activeDefaultColorWrites = true;
VkRenderPass recordingRenderPass = VK_NULL_HANDLE;
VkFramebuffer recordingFramebuffer = VK_NULL_HANDLE;
Bool cmdBufferBegun = false;
Bool recording = false;
Bool frameSubmitted = false;
FloatVec4 clearColor = {0.0f, 0.0f, 0.0f, 1.0f};
Float clearDepth = 1.0f;
UnorderedMap<SharedPtr<FramebufferObject>, PendingClearInfo> pendingClears;
Vector<VkImageLayout> swapchainImageLayouts;
};
BackendState g;
void ClearFrameTrashBuffers(); void ClearFrameTrashBuffers();
void ClearFrameTrashImages(); void ClearFrameTrashImages();
@@ -269,8 +50,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
res.size = 0; res.size = 0;
} }
void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags props, void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags props, BufferResource& out) {
BufferResource& out) {
VkBufferCreateInfo bci{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; VkBufferCreateInfo bci{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
bci.size = size; bci.size = size;
bci.usage = usage; bci.usage = usage;
@@ -346,8 +126,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
VkBufferUsageFlags usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VkBufferUsageFlags usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT; VK_BUFFER_USAGE_TRANSFER_DST_BIT;
VkMemoryPropertyFlags props = VkMemoryPropertyFlags props = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
CreateBuffer(size, usage, props, res); CreateBuffer(size, usage, props, res);
res.lastUsedFrame = ~0u; res.lastUsedFrame = ~0u;
} }
@@ -705,8 +484,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
VkAttachmentDescription depth{}; VkAttachmentDescription depth{};
depth.format = g.depthFormat; depth.format = g.depthFormat;
depth.samples = VK_SAMPLE_COUNT_1_BIT; depth.samples = VK_SAMPLE_COUNT_1_BIT;
depth.loadOp = depth.loadOp = (clearMask & GL_DEPTH_BUFFER_BIT) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
(clearMask & GL_DEPTH_BUFFER_BIT) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
depth.storeOp = VK_ATTACHMENT_STORE_OP_STORE; depth.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if (AspectForFormat(g.depthFormat) & VK_IMAGE_ASPECT_STENCIL_BIT) { if (AspectForFormat(g.depthFormat) & VK_IMAGE_ASPECT_STENCIL_BIT) {
depth.stencilLoadOp = depth.stencilLoadOp =
@@ -855,8 +633,8 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
return view; return view;
} }
void CmdTransitionImageLayout(VkCommandBuffer cmd, VkImage image, VkImageLayout oldLayout, void CmdTransitionImageLayout(VkCommandBuffer cmd, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout,
VkImageLayout newLayout, VkImageAspectFlags aspect) { VkImageAspectFlags aspect) {
VkImageMemoryBarrier barrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER}; VkImageMemoryBarrier barrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
barrier.oldLayout = oldLayout; barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout; barrier.newLayout = newLayout;
@@ -889,8 +667,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && } else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = 0; barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
@@ -901,8 +678,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && } else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
barrier.srcAccessMask = 0; barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
@@ -951,26 +727,22 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && } else if (oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
barrier.srcAccessMask = 0; barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && } else if (oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
barrier.srcAccessMask = 0; barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.dstAccessMask = 0; barrier.dstAccessMask = 0;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; dstStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = 0; barrier.dstAccessMask = 0;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
@@ -1023,14 +795,12 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
void EnsureImageLayout(VkImage image, VkImageLayout& currentLayout, VkImageLayout desiredLayout, void EnsureImageLayout(VkImage image, VkImageLayout& currentLayout, VkImageLayout desiredLayout,
VkImageAspectFlags aspect) { VkImageAspectFlags aspect) {
if (currentLayout == desiredLayout) return; if (currentLayout == desiredLayout) return;
SubmitImmediate([&](VkCommandBuffer cmd) { SubmitImmediate(
CmdTransitionImageLayout(cmd, image, currentLayout, desiredLayout, aspect); [&](VkCommandBuffer cmd) { CmdTransitionImageLayout(cmd, image, currentLayout, desiredLayout, aspect); });
});
currentLayout = desiredLayout; currentLayout = desiredLayout;
} }
void EnsureImageLayoutForDescriptor(TextureResource& res, VkImageAspectFlags aspect, void EnsureImageLayoutForDescriptor(TextureResource& res, VkImageAspectFlags aspect, VkImageLayout desiredLayout) {
VkImageLayout desiredLayout) {
if (res.image == VK_NULL_HANDLE) return; if (res.image == VK_NULL_HANDLE) return;
if (res.layout == desiredLayout) return; if (res.layout == desiredLayout) return;
if (!g.cmdBufferBegun) { if (!g.cmdBufferBegun) {
@@ -1098,8 +868,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
region.imageSubresource.baseArrayLayer = 0; region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = 1;
region.imageExtent = extent; region.imageExtent = extent;
vkCmdCopyBufferToImage(cmd, staging.buffer, res.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, vkCmdCopyBufferToImage(cmd, staging.buffer, res.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
&region);
CmdTransitionImageLayout(cmd, res.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, sampledLayout, aspect); CmdTransitionImageLayout(cmd, res.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, sampledLayout, aspect);
}); });
@@ -1127,8 +896,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
region.srcSubresource.baseArrayLayer = 0; region.srcSubresource.baseArrayLayer = 0;
region.srcSubresource.layerCount = 1; region.srcSubresource.layerCount = 1;
region.dstSubresource = region.srcSubresource; region.dstSubresource = region.srcSubresource;
region.extent = {std::max(1u, dst.extent.width >> level), std::max(1u, dst.extent.height >> level), region.extent = {std::max(1u, dst.extent.width >> level), std::max(1u, dst.extent.height >> level), 1};
1};
vkCmdCopyImage(cmd, src.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst.image, vkCmdCopyImage(cmd, src.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst.image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
} }
@@ -1144,8 +912,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
auto& res = g.textures[tex]; auto& res = g.textures[tex];
VkFormat fmt = ToVkFormat(tex->GetFormat()); VkFormat fmt = ToVkFormat(tex->GetFormat());
auto size = tex->GetBaseSize(); auto size = tex->GetBaseSize();
VkExtent3D extent{static_cast<Uint32>(std::max(1, size.x())), static_cast<Uint32>(std::max(1, size.y())), VkExtent3D extent{static_cast<Uint32>(std::max(1, size.x())), static_cast<Uint32>(std::max(1, size.y())), 1};
1};
Uint32 mipLevels = 1; Uint32 mipLevels = 1;
if (tex->GetStorageType() == TextureStorageType::Mipmap) { if (tex->GetStorageType() == TextureStorageType::Mipmap) {
auto* mip = dynamic_cast<TextureObjectMipmap*>(tex); auto* mip = dynamic_cast<TextureObjectMipmap*>(tex);
@@ -1174,8 +941,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
if (canCopy) { if (canCopy) {
CopyImageMipLevels(oldRes, res); CopyImageMipLevels(oldRes, res);
} }
if (oldRes.image != VK_NULL_HANDLE || oldRes.view != VK_NULL_HANDLE || if (oldRes.image != VK_NULL_HANDLE || oldRes.view != VK_NULL_HANDLE || oldRes.memory != VK_NULL_HANDLE) {
oldRes.memory != VK_NULL_HANDLE) {
TrashImageResource(oldRes); TrashImageResource(oldRes);
} }
} }
@@ -1195,8 +961,8 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
VkExtent2D extent{static_cast<Uint32>(std::max(1, rbo->GetWidth())), VkExtent2D extent{static_cast<Uint32>(std::max(1, rbo->GetWidth())),
static_cast<Uint32>(std::max(1, rbo->GetHeight()))}; static_cast<Uint32>(std::max(1, rbo->GetHeight()))};
Bool needCreate = !res.valid || res.format != fmt || res.extent.width != extent.width || Bool needCreate =
res.extent.height != extent.height; !res.valid || res.format != fmt || res.extent.width != extent.width || res.extent.height != extent.height;
if (needCreate) { if (needCreate) {
DestroyRenderbuffer(res); DestroyRenderbuffer(res);
res.format = fmt; res.format = fmt;
@@ -1373,8 +1139,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
} }
Int32 idx = newIndex[static_cast<SizeT>(buf)]; Int32 idx = newIndex[static_cast<SizeT>(buf)];
if (idx < 0) { if (idx < 0) {
MGLOG_W("Framebuffer %u draw buffer %u refers to missing attachment", stateFBO->GetExternalIndex(), MGLOG_W("Framebuffer %u draw buffer %u refers to missing attachment", stateFBO->GetExternalIndex(), i);
i);
continue; continue;
} }
drawAttachmentIndices[i] = idx; drawAttachmentIndices[i] = idx;
@@ -1472,8 +1237,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
fbci.width = extent.width; fbci.width = extent.width;
fbci.height = extent.height; fbci.height = extent.height;
fbci.layers = 1; fbci.layers = 1;
VK_VERIFY(vkCreateFramebuffer(g.ctx->GetDevice(), &fbci, nullptr, &backend.framebuffer), VK_VERIFY(vkCreateFramebuffer(g.ctx->GetDevice(), &fbci, nullptr, &backend.framebuffer), "vkCreateFramebuffer");
"vkCreateFramebuffer");
return true; return true;
} }
@@ -1780,11 +1544,9 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
if (normalized) { if (normalized) {
switch (type) { switch (type) {
case DataType::Int8: case DataType::Int8:
return pick(VK_FORMAT_R8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8B8_SNORM, return pick(VK_FORMAT_R8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8B8_SNORM, VK_FORMAT_R8G8B8A8_SNORM);
VK_FORMAT_R8G8B8A8_SNORM);
case DataType::Uint8: case DataType::Uint8:
return pick(VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8B8_UNORM, return pick(VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8B8_UNORM, VK_FORMAT_R8G8B8A8_UNORM);
VK_FORMAT_R8G8B8A8_UNORM);
case DataType::Int16: case DataType::Int16:
return pick(VK_FORMAT_R16_SNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16B16_SNORM, return pick(VK_FORMAT_R16_SNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16B16_SNORM,
VK_FORMAT_R16G16B16A16_SNORM); VK_FORMAT_R16G16B16A16_SNORM);
@@ -1951,8 +1713,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
spvc_parsed_ir ir = nullptr; spvc_parsed_ir ir = nullptr;
spvc_context_parse_spirv(context, spv.data(), spv.size(), &ir); spvc_context_parse_spirv(context, spv.data(), spv.size(), &ir);
spvc_compiler compiler = nullptr; spvc_compiler compiler = nullptr;
spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler);
&compiler);
spvc_resources resources = nullptr; spvc_resources resources = nullptr;
spvc_compiler_create_shader_resources(compiler, &resources); spvc_compiler_create_shader_resources(compiler, &resources);
@@ -2247,10 +2008,9 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
return XXH64(keys, sizeof(keys), 0xBADC0FFEEu); return XXH64(keys, sizeof(keys), 0xBADC0FFEEu);
} }
VkPipeline GetOrCreatePipeline(ProgramResource& prog, const VertexArrayObject* vao, VkPipeline GetOrCreatePipeline(ProgramResource& prog, const VertexArrayObject* vao, const RenderStateParameters& rs,
const RenderStateParameters& rs, VkPrimitiveTopology topology, VkPrimitiveTopology topology, VkRenderPass renderPass, Uint32 colorAttachmentCount,
VkRenderPass renderPass, Uint32 colorAttachmentCount, Bool hasDepth, Bool hasDepth, Uint64 renderPassKey) {
Uint64 renderPassKey) {
if (!g.programMgr) g.programMgr = MakeUnique<DV::ProgramManager>(*g.ctx); if (!g.programMgr) g.programMgr = MakeUnique<DV::ProgramManager>(*g.ctx);
prog.shaderStages = &g.programMgr->CreatePipelineShaderStages(prog.program, GetShaderTransformFlags()); prog.shaderStages = &g.programMgr->CreatePipelineShaderStages(prog.program, GetShaderTransformFlags());
if (!prog.shaderStages || prog.shaderStages->empty()) { if (!prog.shaderStages || prog.shaderStages->empty()) {
@@ -2597,8 +2357,8 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
g.defaultTexture.extent = {1, 1, 1}; g.defaultTexture.extent = {1, 1, 1};
g.defaultTexture.mipLevels = 1; g.defaultTexture.mipLevels = 1;
CreateImage(g.defaultTexture.extent, g.defaultTexture.format, CreateImage(g.defaultTexture.extent, g.defaultTexture.format,
UsageForTextureFormat(g.defaultTexture.format), g.defaultTexture.image, UsageForTextureFormat(g.defaultTexture.format), g.defaultTexture.image, g.defaultTexture.memory,
g.defaultTexture.memory, g.defaultTexture.mipLevels); g.defaultTexture.mipLevels);
g.defaultTexture.view = g.defaultTexture.view =
CreateImageView(g.defaultTexture.image, g.defaultTexture.format, VK_IMAGE_ASPECT_COLOR_BIT); CreateImageView(g.defaultTexture.image, g.defaultTexture.format, VK_IMAGE_ASPECT_COLOR_BIT);
g.defaultTexture.layout = VK_IMAGE_LAYOUT_UNDEFINED; g.defaultTexture.layout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -2673,8 +2433,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
SubmitImmediate([&](VkCommandBuffer cmd) { SubmitImmediate([&](VkCommandBuffer cmd) {
CmdTransitionImageLayout(cmd, g.depthImage, VK_IMAGE_LAYOUT_UNDEFINED, CmdTransitionImageLayout(cmd, g.depthImage, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, AspectForFormat(g.depthFormat));
AspectForFormat(g.depthFormat));
}); });
} }
@@ -2753,8 +2512,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
void BeginCommandBuffer() { void BeginCommandBuffer() {
if (g.cmdBufferBegun) return; if (g.cmdBufferBegun) return;
auto& frame = *g.frames[g.currentFrame]; auto& frame = *g.frames[g.currentFrame];
VK_VERIFY(vkWaitForFences(g.ctx->GetDevice(), 1, &frame.InFlightFence, VK_TRUE, UINT64_MAX), VK_VERIFY(vkWaitForFences(g.ctx->GetDevice(), 1, &frame.InFlightFence, VK_TRUE, UINT64_MAX), "vkWaitForFences");
"vkWaitForFences");
VK_VERIFY(vkResetFences(g.ctx->GetDevice(), 1, &frame.InFlightFence), "vkResetFences"); VK_VERIFY(vkResetFences(g.ctx->GetDevice(), 1, &frame.InFlightFence), "vkResetFences");
ClearFrameTrashBuffers(); ClearFrameTrashBuffers();
ClearFrameTrashImages(); ClearFrameTrashImages();
@@ -2853,8 +2611,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
if ((pendingMask & GL_DEPTH_BUFFER_BIT) && g.activeHasDepth && (depthAspect & VK_IMAGE_ASPECT_DEPTH_BIT)) { if ((pendingMask & GL_DEPTH_BUFFER_BIT) && g.activeHasDepth && (depthAspect & VK_IMAGE_ASPECT_DEPTH_BIT)) {
effectiveMask |= GL_DEPTH_BUFFER_BIT; effectiveMask |= GL_DEPTH_BUFFER_BIT;
} }
if ((pendingMask & GL_STENCIL_BUFFER_BIT) && g.activeHasDepth && if ((pendingMask & GL_STENCIL_BUFFER_BIT) && g.activeHasDepth && (depthAspect & VK_IMAGE_ASPECT_STENCIL_BIT)) {
(depthAspect & VK_IMAGE_ASPECT_STENCIL_BIT)) {
effectiveMask |= GL_STENCIL_BUFFER_BIT; effectiveMask |= GL_STENCIL_BUFFER_BIT;
} }
@@ -2917,8 +2674,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
VkClearAttachment color{}; VkClearAttachment color{};
color.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; color.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
color.colorAttachment = i; color.colorAttachment = i;
color.clearValue.color = {g.clearColor.x(), g.clearColor.y(), g.clearColor.z(), color.clearValue.color = {g.clearColor.x(), g.clearColor.y(), g.clearColor.z(), g.clearColor.w()};
g.clearColor.w()};
atts.push_back(color); atts.push_back(color);
} }
} }
@@ -3051,7 +2807,6 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
} }
frame.TrashImages.clear(); frame.TrashImages.clear();
} }
} // namespace
void FrameBegin() { void FrameBegin() {
EnsureInitialized(); EnsureInitialized();
@@ -3097,6 +2852,11 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
FrameBeginInternal(); FrameBeginInternal();
} }
const VulkanState& GetVulkanState() {
EnsureInitialized();
return g;
}
void InitVulkan(ANativeWindow* window) { void InitVulkan(ANativeWindow* window) {
if (g.initialized) return; if (g.initialized) return;
+218 -1
View File
@@ -8,11 +8,229 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
#include "Renderer/VkCommon.h"
#include "Renderer/VulkanContext.h"
#include "Renderer/SwapchainManager.h"
#include "Renderer/FrameContext.h"
#include "Managers/ProgramManager.h"
#include <MG_State/GLState/Core.h>
namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl { namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
namespace DV = MobileGL::MG_Backend::DirectVulkan::VkManager;
using BufferObject = MobileGL::MG_State::GLState::BufferObject;
using ProgramObject = MobileGL::MG_State::GLState::ProgramObject;
using VertexArrayObject = MobileGL::MG_State::GLState::VertexArrayObject;
using FramebufferObject = MobileGL::MG_State::GLState::FramebufferObject;
using FramebufferAttachmentObject = MobileGL::MG_State::GLState::FramebufferAttachmentObject;
using ITextureObject = MobileGL::MG_State::GLState::ITextureObject;
using RenderbufferObject = MobileGL::MG_State::GLState::RenderbufferObject;
using SamplerObject = MobileGL::MG_State::GLState::SamplerObject;
using TextureObjectMipmap = MobileGL::MG_State::GLState::TextureObjectMipmap;
using TrashImage = MobileGL::MG_Backend::DirectVulkan::TrashImage;
struct BufferResource {
VkBuffer buffer = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
VkDeviceSize size = 0;
VkBufferUsageFlags usage = 0;
VkMemoryPropertyFlags props = 0;
void* mapped = nullptr;
Uint32 lastUsedFrame = ~0u;
};
struct TextureResource {
VkImage image = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
UnorderedMap<Uint32, VkImageView> mipViews;
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent3D extent{0, 0, 1};
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
Uint32 mipLevels = 1;
Uint16 paramsVersion = 0;
bool valid = false;
};
struct RenderbufferResource {
VkImage image = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent2D extent{0, 0};
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
bool valid = false;
};
struct SamplerResource {
VkSampler sampler = VK_NULL_HANDLE;
Uint16 version = 0;
SamplerParameters params{};
};
struct PendingClearInfo {
GLbitfield mask = 0;
FloatVec4 clearColor = {0.0f, 0.0f, 0.0f, 1.0f};
Float clearDepth = 1.0f;
};
struct UniformBindingInfo {
String name;
Uint32 binding = 0;
Uint32 set = 0;
Uint32 blockIndex = 0xFFFFFFFFu;
VkShaderStageFlags stages = 0;
};
struct SamplerBindingInfo {
String name;
Uint32 binding = 0;
Uint32 set = 0;
VkShaderStageFlags stages = 0;
};
struct ProgramResource {
ProgramObject* program = nullptr;
Uint64 spvHash = 0;
DV::ProgramManager::HashType programHash = 0;
Vector<VkPipelineShaderStageCreateInfo>* shaderStages = nullptr;
VkDescriptorSetLayout setLayout = VK_NULL_HANDLE;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
struct UboPool {
Vector<BufferResource> buffers;
Uint32 cursor = 0;
};
Vector<UboPool> uboPools;
SizeT uboSize = 0;
Int32 uboBinding = -1;
Uint32 uniformDescriptorCount = 0;
Uint32 samplerDescriptorCount = 0;
Vector<UniformBindingInfo> uniformBindings;
Vector<SamplerBindingInfo> samplerBindings;
UnorderedMap<String, Uint32> samplerBindingByName;
UnorderedMap<Uint64, VkPipeline> pipelines;
};
struct DescriptorPoolConfig {
Uint32 maxSets = 0;
Uint32 uniformCount = 0;
Uint32 samplerCount = 0;
};
struct FrameDescriptorPools {
Vector<VkDescriptorPool> pools;
DescriptorPoolConfig config;
Uint32 activePool = 0;
};
struct VertexAttribKey {
Uint8 enabled = 0;
Uint8 size = 0;
Uint8 type = 0;
Uint8 normalized = 0;
Uint8 isInteger = 0;
Uint8 divisor = 0;
Uint16 pad = 0;
Uint32 stride = 0;
Uint64 offset = 0;
};
struct AttachmentInfo {
FramebufferAttachmentType type = FramebufferAttachmentType::None;
VkImageView view = VK_NULL_HANDLE;
VkFormat format = VK_FORMAT_UNDEFINED;
VkImageAspectFlags aspect = 0;
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ITextureObject* texture = nullptr;
RenderbufferObject* renderbuffer = nullptr;
};
struct BackendFramebufferObject {
Array<VkRenderPass, 8> renderPasses = {};
VkFramebuffer framebuffer = VK_NULL_HANDLE;
VkExtent2D extent{0, 0};
Uint32 colorAttachmentCount = 0;
Bool hasDepth = false;
VkFormat depthFormat = VK_FORMAT_UNDEFINED;
Uint64 renderPassCompatHash = 0;
Vector<AttachmentInfo> attachments;
Array<Int32, static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)> attachmentIndex =
{};
FramebufferObject::FramebufferAttachmentVersionArray syncedAttachmentVersions = {0};
FramebufferObject::FramebufferAttachmentArray frontendDrawBuffers = {FramebufferAttachmentType::None};
Array<Int32, FramebufferObject::MAX_DRAW_BUFFERS> drawBufferAttachmentIndices = {};
FramebufferAttachmentType frontendReadBuffer = FramebufferAttachmentType::Color0;
Uint64 configHash = 0;
Uint16 objectVersion = 0;
Bool IsValid() const { return renderPasses[0] != VK_NULL_HANDLE && framebuffer != VK_NULL_HANDLE; }
};
struct VulkanState {
UniquePtr<DV::VulkanContext> ctx;
UniquePtr<DV::SwapchainManager> swapchain;
UniquePtr<DV::ProgramManager> programMgr;
Array<VkRenderPass, 8> renderPasses = {};
VkCommandPool commandPool = VK_NULL_HANDLE;
Vector<UniquePtr<DV::FrameContext>> frames;
Vector<FrameDescriptorPools> frameDescriptorPools;
Uint32 currentFrame = 0;
Uint32 maxFramesInFlight = 2;
Bool initialized = false;
UintVec2 viewportSize{0, 0};
VkImage depthImage = VK_NULL_HANDLE;
VkDeviceMemory depthMemory = VK_NULL_HANDLE;
VkImageView depthView = VK_NULL_HANDLE;
VkFormat depthFormat = VK_FORMAT_UNDEFINED;
Uint64 defaultRenderPassCompatHash = 0;
BufferResource nullUbo;
TextureResource defaultTexture;
SamplerResource defaultSampler;
UnorderedMap<const BufferObject*, BufferResource> buffers;
UnorderedMap<const ITextureObject*, TextureResource> textures;
UnorderedMap<const RenderbufferObject*, RenderbufferResource> renderbuffers;
UnorderedMap<const SamplerObject*, SamplerResource> samplers;
UnorderedMap<const ProgramObject*, ProgramResource> programs;
UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>> framebuffers;
VkRenderPass activeRenderPass = VK_NULL_HANDLE;
VkFramebuffer activeFramebuffer = VK_NULL_HANDLE;
VkExtent2D activeExtent{0, 0};
Uint32 activeColorAttachmentCount = 1;
Bool activeHasDepth = false;
VkFormat activeDepthFormat = VK_FORMAT_UNDEFINED;
SharedPtr<MG_State::GLState::FramebufferObject> activeStateFBO = nullptr;
SharedPtr<BackendFramebufferObject> activeBackendFBO = nullptr;
Bool activeIsDefault = true;
Bool activeDefaultColorWrites = true;
VkRenderPass recordingRenderPass = VK_NULL_HANDLE;
VkFramebuffer recordingFramebuffer = VK_NULL_HANDLE;
Bool cmdBufferBegun = false;
Bool recording = false;
Bool frameSubmitted = false;
FloatVec4 clearColor = {0.0f, 0.0f, 0.0f, 1.0f};
Float clearDepth = 1.0f;
UnorderedMap<SharedPtr<FramebufferObject>, PendingClearInfo> pendingClears;
Vector<VkImageLayout> swapchainImageLayouts;
};
void Present(); void Present();
void FrameBegin(); void FrameBegin();
void InitVulkan(ANativeWindow* window); void InitVulkan(ANativeWindow* window);
const VulkanState& GetVulkanState();
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value); void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value); void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
@@ -49,5 +267,4 @@ namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl {
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
GLsizei height); GLsizei height);
void GenerateMipmap(GLenum target); void GenerateMipmap(GLenum target);
void Present();
} // namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl } // namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl
@@ -7,8 +7,6 @@
// End of Source File Header // End of Source File Header
#include "GL_Getter.h" #include "GL_Getter.h"
#include "GL/gl.h"
#include "MG_Util/Debug/Log.h"
#include <Config.h> #include <Config.h>
#include <MGGitHash.h> #include <MGGitHash.h>
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
@@ -31,8 +31,9 @@ namespace MobileGL {
// Compile for OpenGL here, so that we can do validation and link // Compile for OpenGL here, so that we can do validation and link
// like a real OpenGL driver at linking stage // like a real OpenGL driver at linking stage
// Will compile for other backends later. // Will compile for other backends later.
ShaderAttrib attrib{ ShaderAttrib attrib{.shaderType = MG_Util::ConvertShaderStageToGLEnum(m_stage),
.shaderType = MG_Util::ConvertShaderStageToGLEnum(m_stage), .sourceStr = m_source, .flags = ShaderCompileBits::CompileForOpenGL}; .sourceStr = m_source,
.flags = ShaderCompileBits::CompileForOpenGL};
auto result = ShaderCompiler::CompileShader(attrib); auto result = ShaderCompiler::CompileShader(attrib);
if (result) { if (result) {
@@ -0,0 +1,51 @@
// MobileGL - MobileGL/MG_Util/BackendLoaders/Vulkan/Loader.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 "Loader.h"
namespace MobileGL::MG_Util::BackendLoader {
inline Version DecodeApiVersion(uint32_t version) {
return {(Int)VK_VERSION_MAJOR(version), (Int)VK_VERSION_MINOR(version), (Int)VK_VERSION_PATCH(version)};
}
inline std::string DecodeDriverVersion(uint32_t driverVersion) {
std::ostringstream oss;
oss << VK_VERSION_MAJOR(driverVersion) << "." << VK_VERSION_MINOR(driverVersion) << "."
<< VK_VERSION_PATCH(driverVersion);
return oss.str();
}
Bool QueryVulkanCapabilities(MobileGL::MG_External::VulkanCapabilities& caps, VkPhysicalDevice physicalDevice) {
if (!physicalDevice) {
MGLOG_E("Invalid physical device handle");
return false;
}
VkPhysicalDeviceProperties props{};
vkGetPhysicalDeviceProperties(physicalDevice, &props);
if (props.apiVersion < VK_API_VERSION_1_1) {
MGLOG_E("Vulkan API version %u.%u.%u is not supported, requires at least 1.1",
VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion),
VK_VERSION_PATCH(props.apiVersion));
return false;
}
VkPhysicalDeviceProperties2 props2{};
props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
vkGetPhysicalDeviceProperties2(physicalDevice, &props2);
const VkPhysicalDeviceProperties& p = props2.properties;
caps.VulkanAPIVersion = DecodeApiVersion(p.apiVersion);
caps.DeviceName = p.deviceName;
caps.DriverVersionString = DecodeDriverVersion(p.driverVersion);
caps.UniformBufferOffsetAlignment = static_cast<int>(p.limits.minUniformBufferOffsetAlignment);
return true;
}
} // namespace MobileGL::MG_Util::BackendLoader
@@ -0,0 +1,24 @@
// MobileGL - MobileGL/MG_Util/BackendLoaders/Vulkan/Loader.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>
namespace MobileGL {
namespace MG_External {
struct VulkanCapabilities {
Version VulkanAPIVersion{1, 0, 0};
String DeviceName;
String DriverVersionString;
Int UniformBufferOffsetAlignment = 256;
};
} // namespace MG_External
namespace MG_Util::BackendLoader {
Bool QueryVulkanCapabilities(MobileGL::MG_External::VulkanCapabilities& caps, VkPhysicalDevice physicalDevice);
} // namespace MG_Util::BackendLoader
} // namespace MobileGL