From dcb8bb1871b4c417dcaf178f726903ddfa883144 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 18 Feb 2026 00:12:06 +0800 Subject: [PATCH] [Chore] (MG_Backend/DirectVulkan): simplifying draw payload --- .../MG_Backend/DirectVulkan/DirectVulkan.cpp | 52 +---------------- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 58 ++++++++++++++----- .../DirectVulkan/Renderer/VulkanRenderer.h | 13 +---- 3 files changed, 45 insertions(+), 78 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index 504d3ac9..7e5605cf 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -101,32 +101,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { payload.drawArray.program = currentProgram ? currentProgram.get() : nullptr; payload.drawArray.vertexArray = vao.get(); payload.indexType = type; - payload.indexData = indexData->data() + byteOffset; - payload.indexDataSizeBytes = requiredBytes; - - const auto& attr0 = vao->GetAttribute(0); - if (attr0.Enabled && attr0.Buffer) { - const auto positionData = attr0.Buffer->GetDataReadOnly(); - if (positionData && !positionData->empty()) { - payload.drawArray.hasPositionStream = true; - payload.drawArray.positionData = positionData->data(); - payload.drawArray.positionDataSizeBytes = attr0.Buffer->GetSize(); - payload.drawArray.positionOffsetBytes = attr0.Offset; - payload.drawArray.positionStrideBytes = attr0.Stride > 0 ? static_cast(attr0.Stride) : 0; - payload.drawArray.positionSize = attr0.Size; - payload.drawArray.positionNormalized = attr0.Normalized; - - switch (attr0.Type) { - case DataType::Float32: - payload.drawArray.positionType = GL_FLOAT; - break; - default: - payload.drawArray.positionType = GL_FLOAT; - payload.drawArray.hasPositionStream = false; - break; - } - } - } + payload.indexByteOffset = byteOffset; pVulkanRenderer->DrawElements(payload); } @@ -163,31 +138,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { const auto vao = MG_State::pGLContext->GetBoundVertexArray(); payload.vertexArray = vao ? vao.get() : nullptr; - if (vao) { - const auto& attr0 = vao->GetAttribute(0); - if (attr0.Enabled && attr0.Buffer) { - const auto positionData = attr0.Buffer->GetDataReadOnly(); - if (positionData && !positionData->empty()) { - payload.hasPositionStream = true; - payload.positionData = positionData->data(); - payload.positionDataSizeBytes = attr0.Buffer->GetSize(); - payload.positionOffsetBytes = attr0.Offset; - payload.positionStrideBytes = attr0.Stride > 0 ? static_cast(attr0.Stride) : 0; - payload.positionSize = attr0.Size; - payload.positionNormalized = attr0.Normalized; - - switch (attr0.Type) { - case DataType::Float32: - payload.positionType = GL_FLOAT; - break; - default: - payload.positionType = GL_FLOAT; - payload.hasPositionStream = false; - break; - } - } - } - } pVulkanRenderer->DrawArrays(payload); } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index e7d7c878..b1b6dad5 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -571,7 +571,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool VulkanRenderer::UploadAndBindVertexStreams( const VertexInputStateFactory::BackendVertexInputState& vertexInputState, - const MG_State::GLState::VertexArrayObject& vertexArray, + const DrawArrayPayload& payload, VkCommandBuffer commandBuffer) { if (vertexInputState.bindings.empty()) { return true; @@ -590,19 +590,27 @@ namespace MobileGL::MG_Backend::DirectVulkan { Vector vkBuffers(bindingCount, VK_NULL_HANDLE); Vector vkOffsets(bindingCount, 0); - for (SizeT binding = 0; binding < bindingCount; ++binding) { - const SizeT bufferKey = vertexInputState.bindingBufferKeys[binding]; - const MG_State::GLState::BufferObject* sourceBuffer = nullptr; + auto findBufferByKey = [&](SizeT bufferKey) -> const MG_State::GLState::BufferObject* { + if (!payload.vertexArray) { + return nullptr; + } + const auto& attrs = payload.vertexArray->GetAllAttributes(); for (Uint32 location = 0; location < MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS; ++location) { - const auto& attr = vertexArray.GetAttribute(location); - if (!attr.Enabled || !attr.Buffer) { + const auto& attr = attrs[location]; + if (!attr.Buffer) { continue; } - if (reinterpret_cast(attr.Buffer.get()) == bufferKey) { - sourceBuffer = attr.Buffer.get(); - break; + const auto* buffer = attr.Buffer.get(); + if (reinterpret_cast(buffer) == bufferKey) { + return buffer; } } + return nullptr; + }; + + for (SizeT binding = 0; binding < bindingCount; ++binding) { + const SizeT bufferKey = vertexInputState.bindingBufferKeys[binding]; + const MG_State::GLState::BufferObject* sourceBuffer = findBufferByKey(bufferKey); if (!sourceBuffer) { MGLOG_W("UploadAndBindVertexStreams skipped: no source buffer for binding %zu", binding); @@ -709,7 +717,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { MGLOG_W("DrawArrays skipped: vertex input requires VAO"); return; } - if (!UploadAndBindVertexStreams(*vertexInputState, *payload.vertexArray, commandBuffer)) { + if (!UploadAndBindVertexStreams(*vertexInputState, payload, commandBuffer)) { return; } } @@ -757,8 +765,25 @@ namespace MobileGL::MG_Backend::DirectVulkan { return; } - MOBILEGL_ASSERT(payload.indexData != nullptr, "DrawElements requires non-null indexData"); - MOBILEGL_ASSERT(payload.indexDataSizeBytes > 0, "DrawElements requires non-zero index data size"); + if (payload.drawArray.vertexArray == nullptr) { + MGLOG_W("DrawElements skipped: no VAO provided"); + return; + } + + // VertexArrayObject currently exposes index-buffer binding through non-const accessor. + auto* vao = const_cast(payload.drawArray.vertexArray); + const auto indexBuffer = vao->GetIndexBufferBindingSlot().GetBoundObject(); + if (!indexBuffer) { + MGLOG_W("DrawElements skipped: VAO has no bound ELEMENT_ARRAY_BUFFER"); + return; + } + + const auto indexData = indexBuffer->GetDataReadOnly(); + MOBILEGL_ASSERT(indexData != nullptr && !indexData->empty(), "DrawElements requires non-empty EBO data"); + const SizeT indexSize = (payload.indexType == GL_UNSIGNED_SHORT) ? sizeof(Uint16) : sizeof(Uint32); + const SizeT indexDataSizeBytes = static_cast(payload.drawArray.count) * indexSize; + MOBILEGL_ASSERT(payload.indexByteOffset + indexDataSizeBytes <= indexBuffer->GetSize(), + "DrawElements index range out of bounds"); const VertexInputStateFactory::BackendVertexInputState* vertexInputState = nullptr; if (payload.drawArray.vertexArray && m_vertexInputStateFactory) { @@ -794,10 +819,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { return; } - if (!m_indexBuffer.IsValid() || m_indexBuffer.GetSize() < payload.indexDataSizeBytes) { + if (!m_indexBuffer.IsValid() || m_indexBuffer.GetSize() < indexDataSizeBytes) { DeferDestroyBuffer(m_indexBuffer); const Bool created = m_indexBuffer.Create( - m_allocator, static_cast(payload.indexDataSizeBytes), + m_allocator, static_cast(indexDataSizeBytes), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); @@ -807,7 +832,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } - if (!m_indexBuffer.Upload(payload.indexData, static_cast(payload.indexDataSizeBytes), 0)) { + if (!m_indexBuffer.Upload(indexData->data() + payload.indexByteOffset, static_cast(indexDataSizeBytes), + 0)) { MGLOG_E("DrawElements skipped: failed to upload index data"); return; } @@ -829,7 +855,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { MGLOG_W("DrawElements skipped: vertex input requires VAO"); return; } - if (!UploadAndBindVertexStreams(*vertexInputState, *payload.drawArray.vertexArray, commandBuffer)) { + if (!UploadAndBindVertexStreams(*vertexInputState, payload.drawArray, commandBuffer)) { return; } } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index ec93bce9..6d26ad43 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -35,21 +35,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { GLsizei count = 0; const MG_State::GLState::ProgramObject* program = nullptr; const MG_State::GLState::VertexArrayObject* vertexArray = nullptr; - Bool hasPositionStream = false; - const void* positionData = nullptr; - SizeT positionDataSizeBytes = 0; - SizeT positionStrideBytes = 0; - SizeT positionOffsetBytes = 0; - GLenum positionType = GL_FLOAT; - GLint positionSize = 0; - Bool positionNormalized = false; }; struct DrawElementPayload { DrawArrayPayload drawArray; GLenum indexType = GL_UNSIGNED_SHORT; - const void* indexData = nullptr; - SizeT indexDataSizeBytes = 0; + SizeT indexByteOffset = 0; }; class VulkanRenderer { @@ -185,7 +176,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { void CollectDeferredBufferReleases(Uint32 frameIndex); Bool UploadAndBindVertexStreams( const VertexInputStateFactory::BackendVertexInputState& vertexInputState, - const MG_State::GLState::VertexArrayObject& vertexArray, + const DrawArrayPayload& payload, VkCommandBuffer commandBuffer); void ShutdownSwapchain();