[Chore] (MG_Backend/DirectVulkan): refactor draw cmds

This commit is contained in:
2026-03-17 15:10:17 +08:00
parent 8b9adc5121
commit 87122973be
3 changed files with 94 additions and 63 deletions
@@ -17,10 +17,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
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) {}
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {} void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {}
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLint basevertex) {}
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
GLsizei drawcount, const GLint* basevertex) {}
void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) {} void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) {}
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {} void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {}
@@ -47,65 +43,78 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {} void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {}
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {} void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {}
void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
GLsizei drawcount) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElements called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawElements called with null GL context");
Vector<DrawElementCmd> cmds;
cmds.reserve(static_cast<SizeT>(drawcount));
for (GLsizei i = 0; i < drawcount; ++i) {
if (count[i] == 0) {
continue;
}
DrawElementCmd payload{};
payload.mode = mode;
payload.first = 0;
payload.count = count[i];
payload.indexType = type;
payload.indexByteOffset = reinterpret_cast<SizeT>(indices[i]);
cmds.push_back(payload);
}
if (cmds.empty()) {
return;
}
pVulkanRenderer->MultiDrawElements(cmds);
}
void Clear(GLbitfield mask) { void Clear(GLbitfield mask) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::Clear called with null VulkanRenderer"); MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::Clear called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::Clear called with null GL context"); MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::Clear called with null GL context");
pVulkanRenderer->Clear(mask); pVulkanRenderer->Clear(mask);
} }
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElements called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElements called with null GL context");
DrawElementCmd payload{};
payload.mode = mode;
payload.first = 0;
payload.count = count;
payload.indexType = type;
payload.indexByteOffset = reinterpret_cast<SizeT>(indices);
pVulkanRenderer->DrawElements(payload);
}
void DrawArrays(GLenum mode, GLint first, GLsizei count) { void DrawArrays(GLenum mode, GLint first, GLsizei count) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArrays called with null VulkanRenderer"); MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArrays called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArrays called with null GL context"); MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArrays called with null GL context");
DrawArrayCmd payload{}; DrawCmd payload{};
payload.mode = mode; payload.mode = mode;
payload.first = first; payload.firstVertex = first;
payload.count = count; payload.vertexCount = count;
pVulkanRenderer->DrawArrays(payload); pVulkanRenderer->DrawArrays(payload);
} }
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElements called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElements called with null GL context");
DrawIndexedCmd payload{};
payload.mode = mode;
payload.indexType = type;
payload.indexByteOffset = reinterpret_cast<SizeT>(indices);
payload.indexCount = count;
payload.instanceCount = 1;
pVulkanRenderer->DrawElements(payload);
}
void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
GLsizei drawcount) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElements called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawElements called with null GL context");
// Vector<DrawElementCmd> cmds;
// cmds.reserve(static_cast<SizeT>(drawcount));
// for (GLsizei i = 0; i < drawcount; ++i) {
// if (count[i] == 0) {
// continue;
// }
//
// DrawElementCmd payload{};
// payload.mode = mode;
// payload.firstVertex = 0;
// payload.indexCount = count[i];
// payload.indexType = type;
// payload.indexByteOffset = reinterpret_cast<SizeT>(indices[i]);
// cmds.push_back(payload);
// }
//
// if (cmds.empty()) {
// return;
// }
// pVulkanRenderer->MultiDrawElements(cmds);
}
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLint basevertex) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsBaseVertex called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElementsBaseVertex called with null GL context");
}
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
GLsizei drawcount, const GLint* basevertex) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElements called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawElements called with null GL context");
}
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1,
GLint dstY1, GLbitfield mask, GLenum filter) { GLint dstY1, GLbitfield mask, GLenum filter) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::BlitFramebuffer called with null VulkanRenderer"); MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::BlitFramebuffer called with null VulkanRenderer");
@@ -1191,7 +1191,7 @@ void main() {
1, &blitRegion, filter == GL_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST); 1, &blitRegion, filter == GL_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST);
} }
void VulkanRenderer::DrawArrays(const DrawArrayCmd& payload) { void VulkanRenderer::DrawArrays(const DrawCmd& payload) {
auto& frame = m_frameContext.GetCurrent(); auto& frame = m_frameContext.GetCurrent();
SetupDraw(frame, payload.mode, 0); SetupDraw(frame, payload.mode, 0);
@@ -1200,10 +1200,14 @@ void main() {
VkCommandBuffer& commandBuffer = frame.commandBuffer; VkCommandBuffer& commandBuffer = frame.commandBuffer;
vkCmdDraw(commandBuffer, static_cast<Uint32>(payload.count), 1, static_cast<Uint32>(payload.first), 0); vkCmdDraw(commandBuffer,
payload.vertexCount,
payload.instanceCount,
payload.firstVertex,
payload.firstInstance);
} }
void VulkanRenderer::DrawElements(const DrawElementCmd& payload) { void VulkanRenderer::DrawElements(const DrawIndexedCmd& payload) {
auto& frame = m_frameContext.GetCurrent(); auto& frame = m_frameContext.GetCurrent();
SetupDraw(frame, payload.mode, 0); SetupDraw(frame, payload.mode, 0);
@@ -1231,7 +1235,7 @@ void main() {
const auto indexData = indexBuffer->GetDataReadOnly(); const auto indexData = indexBuffer->GetDataReadOnly();
MOBILEGL_ASSERT(indexData != nullptr && !indexData->empty(), "DrawElements requires non-empty EBO data"); 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 indexSize = (payload.indexType == GL_UNSIGNED_SHORT) ? sizeof(Uint16) : sizeof(Uint32);
const SizeT indexDataSizeBytes = static_cast<SizeT>(payload.count) * indexSize; const SizeT indexDataSizeBytes = static_cast<SizeT>(payload.indexCount) * indexSize;
MOBILEGL_ASSERT(payload.indexByteOffset + indexDataSizeBytes <= indexBuffer->GetSize(), MOBILEGL_ASSERT(payload.indexByteOffset + indexDataSizeBytes <= indexBuffer->GetSize(),
"DrawElements index range out of bounds"); "DrawElements index range out of bounds");
@@ -1256,11 +1260,15 @@ void main() {
VkCommandBuffer& commandBuffer = frame.commandBuffer; VkCommandBuffer& commandBuffer = frame.commandBuffer;
vkCmdBindIndexBuffer(commandBuffer, frameIndexUploadBuffer.GetHandle(), writeOffset, vkIndexType); vkCmdBindIndexBuffer(commandBuffer, frameIndexUploadBuffer.GetHandle(), writeOffset, vkIndexType);
vkCmdDrawIndexed(commandBuffer, static_cast<Uint32>(payload.count), 1, 0, vkCmdDrawIndexed(commandBuffer,
static_cast<Int32>(payload.baseVertex), 0); payload.indexCount,
payload.instanceCount,
payload.firstIndex,
payload.vertexOffset,
payload.firstInstance);
} }
void VulkanRenderer::MultiDrawElements(const Vector<DrawElementCmd>& payloads) { void VulkanRenderer::MultiDrawElements(const Vector<DrawIndexedCmd>& payloads) {
} }
@@ -43,16 +43,30 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Scissor = 1 << 6, Scissor = 1 << 6,
}; };
struct DrawArrayCmd { struct DrawBaseCmd {
GLenum mode = GL_TRIANGLES; GLenum mode = GL_TRIANGLES;
GLint first = 0;
GLsizei count = 0;
}; };
struct DrawElementCmd: public DrawArrayCmd { struct DrawCmd: public DrawBaseCmd {
Uint32 vertexCount = 0;
Uint32 instanceCount = 1;
Uint32 firstVertex = 0;
Uint32 firstInstance = 0;
};
struct DrawIndexedCmd: public DrawBaseCmd {
GLenum indexType = GL_UNSIGNED_SHORT; GLenum indexType = GL_UNSIGNED_SHORT;
SizeT indexByteOffset = 0; SizeT indexByteOffset = 0;
GLint baseVertex = 0;
Uint32 indexCount = 0;
Uint32 instanceCount = 1;
Uint32 firstIndex = 0;
Int32 vertexOffset = 0;
Int32 firstInstance = 0;
};
struct MultiDrawElementsCmd {
}; };
struct QueueFamilyIndices { struct QueueFamilyIndices {
@@ -86,9 +100,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter); GLbitfield mask, GLenum filter);
void DrawArrays(const DrawArrayCmd& payload); void DrawArrays(const DrawCmd& payload);
void DrawElements(const DrawElementCmd& payload); void DrawElements(const DrawIndexedCmd& payload);
void MultiDrawElements(const Vector<DrawElementCmd>& payloads); void MultiDrawElements(const Vector<DrawIndexedCmd>& payloads);
void Present(); void Present();
const PhysicalDevice& GetPhysicalDevice() const; const PhysicalDevice& GetPhysicalDevice() const;