[Chore] (MG_Backend/DirectVulkan): simplifying draw payload

This commit is contained in:
2026-02-18 00:12:06 +08:00
parent 6b656d3f96
commit dcb8bb1871
3 changed files with 45 additions and 78 deletions
@@ -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<SizeT>(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<SizeT>(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);
}
@@ -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<VkBuffer> vkBuffers(bindingCount, VK_NULL_HANDLE);
Vector<VkDeviceSize> 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<SizeT>(attr.Buffer.get()) == bufferKey) {
sourceBuffer = attr.Buffer.get();
break;
const auto* buffer = attr.Buffer.get();
if (reinterpret_cast<SizeT>(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<MG_State::GLState::VertexArrayObject*>(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<SizeT>(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<VkDeviceSize>(payload.indexDataSizeBytes),
m_allocator, static_cast<VkDeviceSize>(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<VkDeviceSize>(payload.indexDataSizeBytes), 0)) {
if (!m_indexBuffer.Upload(indexData->data() + payload.indexByteOffset, static_cast<VkDeviceSize>(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;
}
}
@@ -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();