mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 13:48:30 +09:00
[Feat] (MG_Backend/DirectVulkan): implement simple DrawElements path to put buffer to the test
This commit is contained in:
@@ -24,6 +24,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
|
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
|
||||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElements called with null VulkanRenderer");
|
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElements called with null VulkanRenderer");
|
||||||
|
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElements called with null GL context");
|
||||||
|
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
MGLOG_W("DrawElements skipped: count (%d) must be non-negative", count);
|
MGLOG_W("DrawElements skipped: count (%d) must be non-negative", count);
|
||||||
@@ -39,11 +40,47 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pVulkanRenderer->EnsureFrameRecordingStarted();
|
SizeT indexSize = 0;
|
||||||
|
switch (type) {
|
||||||
|
case GL_UNSIGNED_SHORT:
|
||||||
|
indexSize = sizeof(Uint16);
|
||||||
|
break;
|
||||||
|
case GL_UNSIGNED_INT:
|
||||||
|
indexSize = sizeof(Uint32);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MGLOG_W("DrawElements skipped: index type %u is not supported yet", type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
(void)mode;
|
const auto vao = MG_State::pGLContext->GetBoundVertexArray();
|
||||||
(void)type;
|
if (!vao) {
|
||||||
(void)indices;
|
MGLOG_W("DrawElements skipped: no bound VAO");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto indexBuffer = vao->GetIndexBufferBindingSlot().GetBoundObject();
|
||||||
|
if (!indexBuffer) {
|
||||||
|
MGLOG_W("DrawElements skipped: no bound ELEMENT_ARRAY_BUFFER");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto indexData = indexBuffer->GetDataReadOnly();
|
||||||
|
if (!indexData || indexData->empty()) {
|
||||||
|
MGLOG_W("DrawElements skipped: ELEMENT_ARRAY_BUFFER has no data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SizeT byteOffset = reinterpret_cast<SizeT>(indices);
|
||||||
|
const SizeT requiredBytes = static_cast<SizeT>(count) * indexSize;
|
||||||
|
if (byteOffset + requiredBytes > indexBuffer->GetSize()) {
|
||||||
|
MGLOG_W("DrawElements skipped: index range out of bounds (offset=%zu, size=%zu, buffer=%zu)",
|
||||||
|
byteOffset, requiredBytes, indexBuffer->GetSize());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Uint8* src = indexData->data() + byteOffset;
|
||||||
|
pVulkanRenderer->DrawElements(type, count, src, requiredBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
|
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||||
|
|||||||
@@ -143,6 +143,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
|
VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
|
||||||
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depthStencil{VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
|
||||||
|
depthStencil.depthTestEnable = VK_FALSE;
|
||||||
|
depthStencil.depthWriteEnable = VK_FALSE;
|
||||||
|
depthStencil.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
depthStencil.depthBoundsTestEnable = VK_FALSE;
|
||||||
|
depthStencil.stencilTestEnable = VK_FALSE;
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState colorAttach{};
|
VkPipelineColorBlendAttachmentState colorAttach{};
|
||||||
colorAttach.colorWriteMask =
|
colorAttach.colorWriteMask =
|
||||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||||
@@ -160,6 +167,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
gpi.pViewportState = &vpci;
|
gpi.pViewportState = &vpci;
|
||||||
gpi.pRasterizationState = &raster;
|
gpi.pRasterizationState = &raster;
|
||||||
gpi.pMultisampleState = &ms;
|
gpi.pMultisampleState = &ms;
|
||||||
|
gpi.pDepthStencilState = &depthStencil;
|
||||||
gpi.pColorBlendState = &blend;
|
gpi.pColorBlendState = &blend;
|
||||||
gpi.pDynamicState = &dynamicState;
|
gpi.pDynamicState = &dynamicState;
|
||||||
gpi.layout = m_pipelineLayout;
|
gpi.layout = m_pipelineLayout;
|
||||||
@@ -186,6 +194,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
CreateSurface();
|
CreateSurface();
|
||||||
PickPhysicalDevice();
|
PickPhysicalDevice();
|
||||||
CreateLogicalDeviceAndQueues();
|
CreateLogicalDeviceAndQueues();
|
||||||
|
CreateAllocator();
|
||||||
|
|
||||||
CreateCommandPool();
|
CreateCommandPool();
|
||||||
|
|
||||||
@@ -207,6 +216,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VK_VERIFY(vkDeviceWaitIdle(m_device));
|
VK_VERIFY(vkDeviceWaitIdle(m_device));
|
||||||
|
|
||||||
m_programFactory.reset();
|
m_programFactory.reset();
|
||||||
|
m_indexBuffer.Destroy();
|
||||||
|
|
||||||
m_frameContext.Destroy(m_device, m_commandPool);
|
m_frameContext.Destroy(m_device, m_commandPool);
|
||||||
|
|
||||||
@@ -225,6 +235,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_commandPool = VK_NULL_HANDLE;
|
m_commandPool = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DestroyAllocator();
|
||||||
|
|
||||||
if (m_device != VK_NULL_HANDLE) {
|
if (m_device != VK_NULL_HANDLE) {
|
||||||
vkDestroyDevice(m_device, nullptr);
|
vkDestroyDevice(m_device, nullptr);
|
||||||
m_device = VK_NULL_HANDLE;
|
m_device = VK_NULL_HANDLE;
|
||||||
@@ -462,6 +474,71 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
vkCmdDraw(commandBuffer, static_cast<Uint32>(count), 1, static_cast<Uint32>(first), 0);
|
vkCmdDraw(commandBuffer, static_cast<Uint32>(count), 1, static_cast<Uint32>(first), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanRenderer::DrawElements(GLenum type, GLsizei count, const void* indexData, SizeT indexDataSizeBytes) {
|
||||||
|
EnsureFrameRecordingStarted();
|
||||||
|
auto& frame = m_frameContext.GetCurrent();
|
||||||
|
if (!frame.isCommandRecording || !m_isMainRenderPassActive) {
|
||||||
|
MGLOG_W("DrawElements skipped: frame recording was not started");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkIndexType vkIndexType = VK_INDEX_TYPE_MAX_ENUM;
|
||||||
|
switch (type) {
|
||||||
|
case GL_UNSIGNED_SHORT:
|
||||||
|
vkIndexType = VK_INDEX_TYPE_UINT16;
|
||||||
|
break;
|
||||||
|
case GL_UNSIGNED_INT:
|
||||||
|
vkIndexType = VK_INDEX_TYPE_UINT32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MGLOG_W("DrawElements skipped: index type %u is not supported yet", type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOBILEGL_ASSERT(indexData != nullptr, "DrawElements requires non-null indexData");
|
||||||
|
MOBILEGL_ASSERT(indexDataSizeBytes > 0, "DrawElements requires non-zero index data size");
|
||||||
|
|
||||||
|
if (!m_indexBuffer.IsValid() || m_indexBuffer.GetSize() < indexDataSizeBytes) {
|
||||||
|
m_indexBuffer.Destroy();
|
||||||
|
const Bool created = m_indexBuffer.Create(
|
||||||
|
m_allocator, static_cast<VkDeviceSize>(indexDataSizeBytes),
|
||||||
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO,
|
||||||
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
|
||||||
|
if (!created) {
|
||||||
|
MGLOG_E("DrawElements skipped: failed to create index buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_indexBuffer.Upload(indexData, static_cast<VkDeviceSize>(indexDataSizeBytes), 0)) {
|
||||||
|
MGLOG_E("DrawElements skipped: failed to upload index data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCommandBuffer& commandBuffer = frame.commandBuffer;
|
||||||
|
const auto swapchainExtent = m_swapchainObject.GetExtent();
|
||||||
|
|
||||||
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
|
||||||
|
|
||||||
|
VkViewport viewport{};
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = static_cast<float>(swapchainExtent.width);
|
||||||
|
viewport.height = static_cast<float>(swapchainExtent.height);
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
||||||
|
|
||||||
|
VkRect2D scissor{};
|
||||||
|
scissor.offset = {0, 0};
|
||||||
|
scissor.extent = swapchainExtent;
|
||||||
|
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||||
|
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer.GetHandle(), 0, vkIndexType);
|
||||||
|
vkCmdDrawIndexed(commandBuffer, static_cast<Uint32>(count), 1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanRenderer::Render() {
|
void VulkanRenderer::Render() {
|
||||||
// Route test rendering through the same frame-start logic used by draw calls,
|
// Route test rendering through the same frame-start logic used by draw calls,
|
||||||
// so pending glClear() state can be consumed consistently.
|
// so pending glClear() state can be consumed consistently.
|
||||||
@@ -878,6 +955,31 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MGLOG_I("Queues got successfully.");
|
MGLOG_I("Queues got successfully.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanRenderer::CreateAllocator() {
|
||||||
|
MOBILEGL_ASSERT(m_instance != VK_NULL_HANDLE, "CreateAllocator requires valid VkInstance");
|
||||||
|
MOBILEGL_ASSERT(m_physicalDevice.handle != VK_NULL_HANDLE, "CreateAllocator requires valid physical device");
|
||||||
|
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "CreateAllocator requires valid VkDevice");
|
||||||
|
|
||||||
|
if (m_allocator != nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VmaAllocatorCreateInfo allocatorInfo{};
|
||||||
|
allocatorInfo.instance = m_instance;
|
||||||
|
allocatorInfo.physicalDevice = m_physicalDevice.handle;
|
||||||
|
allocatorInfo.device = m_device;
|
||||||
|
allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_0;
|
||||||
|
|
||||||
|
VK_VERIFY(vmaCreateAllocator(&allocatorInfo, &m_allocator), "vmaCreateAllocator");
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderer::DestroyAllocator() {
|
||||||
|
if (m_allocator != nullptr) {
|
||||||
|
vmaDestroyAllocator(m_allocator);
|
||||||
|
m_allocator = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateSwapchain() {
|
void VulkanRenderer::CreateSwapchain() {
|
||||||
m_swapchainObject.Create(m_device, m_physicalDevice.handle, m_surface,
|
m_swapchainObject.Create(m_device, m_physicalDevice.handle, m_surface,
|
||||||
static_cast<Uint32>(m_physicalDevice.queueFamilies.graphicsFamily),
|
static_cast<Uint32>(m_physicalDevice.queueFamilies.graphicsFamily),
|
||||||
|
|||||||
@@ -11,8 +11,10 @@
|
|||||||
#include "FrameContext.h"
|
#include "FrameContext.h"
|
||||||
#include "ProgramFactory.h"
|
#include "ProgramFactory.h"
|
||||||
#include "SwapchainObject.h"
|
#include "SwapchainObject.h"
|
||||||
|
#include "VkBufferObject.h"
|
||||||
#include "MG_Util/Math/VectorTypes.h"
|
#include "MG_Util/Math/VectorTypes.h"
|
||||||
#include <Includes.h>
|
#include <Includes.h>
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
#include "../VkIncludes.h"
|
#include "../VkIncludes.h"
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Bool ConsumePendingColorClear(VkClearColorValue& outClearColor);
|
Bool ConsumePendingColorClear(VkClearColorValue& outClearColor);
|
||||||
void EnsureFrameRecordingStarted();
|
void EnsureFrameRecordingStarted();
|
||||||
void DrawArrays(GLenum mode, GLint first, GLsizei count);
|
void DrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||||
|
void DrawElements(GLenum type, GLsizei count, const void* indexData, SizeT indexDataSizeBytes);
|
||||||
void Render();
|
void Render();
|
||||||
void Present();
|
void Present();
|
||||||
|
|
||||||
@@ -63,6 +66,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
PhysicalDevice m_physicalDevice;
|
PhysicalDevice m_physicalDevice;
|
||||||
// VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
// VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
|
VmaAllocator m_allocator = nullptr;
|
||||||
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||||
SwapchainObject m_swapchainObject;
|
SwapchainObject m_swapchainObject;
|
||||||
|
|
||||||
@@ -85,6 +89,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||||
|
VkBufferObject m_indexBuffer;
|
||||||
|
|
||||||
Uint m_imageIndexAcquired = 0;
|
Uint m_imageIndexAcquired = 0;
|
||||||
FrameContext m_frameContext;
|
FrameContext m_frameContext;
|
||||||
@@ -103,6 +108,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void CreateSurface();
|
void CreateSurface();
|
||||||
void PickPhysicalDevice();
|
void PickPhysicalDevice();
|
||||||
void CreateLogicalDeviceAndQueues();
|
void CreateLogicalDeviceAndQueues();
|
||||||
|
void CreateAllocator();
|
||||||
|
void DestroyAllocator();
|
||||||
void CreateSwapchain();
|
void CreateSwapchain();
|
||||||
void CreateCommandPool();
|
void CreateCommandPool();
|
||||||
void CreateFrameContexts();
|
void CreateFrameContexts();
|
||||||
|
|||||||
Reference in New Issue
Block a user