From 058ec6d26eaa2ed0114e8bb4f0fb3a709d4ea77b Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 17 Feb 2026 11:33:27 +0800 Subject: [PATCH] [Feat] (MG_Backend/DirectVulkan): implement vao/vbo binding --- .../Renderer/VertexInputStateFactory.cpp | 32 +++++++++++++-- .../MG_Test/Backend/DirectVulkan/TestExec.cpp | 41 ++++++++++++++----- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp index d3affbea..c98d29df 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp @@ -46,6 +46,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { } VertexInputStateBuilder builder; + const void* sourceBuffer = nullptr; + Uint32 sourceStride = 0; + VkVertexInputRate sourceInputRate = VK_VERTEX_INPUT_RATE_VERTEX; + Bool hasBinding = false; + for (Uint32 location = 0; location < MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS; ++location) { const auto& attr = vao.GetAttribute(location); if (!attr.Enabled || !attr.Buffer) { @@ -72,9 +77,30 @@ namespace MobileGL::MG_Backend::DirectVulkan { const VkVertexInputRate inputRate = (attr.Divisor == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; - builder - .AddBinding(location, stride, inputRate) - .AddAttribute(location, location, vkFormat, static_cast(attr.Offset)); + if (!hasBinding) { + sourceBuffer = attr.Buffer.get(); + sourceStride = stride; + sourceInputRate = inputRate; + builder.AddBinding(0, sourceStride, sourceInputRate); + hasBinding = true; + } else { + if (attr.Buffer.get() != sourceBuffer) { + MGLOG_W("Skipping vertex attribute at location %u: only single-buffer vertex input is supported for now", + location); + continue; + } + if (stride != sourceStride) { + MGLOG_W("Skipping vertex attribute at location %u: stride mismatch (%u vs %u) for single-binding path", + location, stride, sourceStride); + continue; + } + if (inputRate != sourceInputRate) { + MGLOG_W("Skipping vertex attribute at location %u: input-rate mismatch for single-binding path", location); + continue; + } + } + + builder.AddAttribute(location, 0, vkFormat, static_cast(attr.Offset)); } const auto& state = builder.Build(); diff --git a/MobileGL/MG_Test/Backend/DirectVulkan/TestExec.cpp b/MobileGL/MG_Test/Backend/DirectVulkan/TestExec.cpp index 6bd6740c..e288f32f 100644 --- a/MobileGL/MG_Test/Backend/DirectVulkan/TestExec.cpp +++ b/MobileGL/MG_Test/Backend/DirectVulkan/TestExec.cpp @@ -134,26 +134,46 @@ int main() { glGenVertexArrays(1, &vao); glBindVertexArray(vao); - static constexpr GLushort kQuadIndices[] = {0, 1, 2, 2, 3, 0}; + static constexpr GLfloat kQuadVertices[] = { + // triangle 1 + -0.6f, -0.6f, 1.0f, 0.0f, 0.0f, + 0.6f, -0.6f, 0.0f, 1.0f, 0.0f, + 0.6f, 0.6f, 0.0f, 0.0f, 1.0f, + // triangle 2 + 0.6f, 0.6f, 1.0f, 0.0f, 0.0f, + -0.6f, 0.6f, 0.0f, 1.0f, 0.0f, + -0.6f, -0.6f, 0.0f, 0.0f, 1.0f + }; + + GLuint vbo = 0; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, static_cast(5 * sizeof(GLfloat)), nullptr); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, static_cast(5 * sizeof(GLfloat)), + reinterpret_cast(2 * sizeof(GLfloat))); + glEnableVertexAttribArray(1); + + static constexpr GLushort kQuadIndices[] = {0, 1, 2, 3, 4, 5}; GLuint ebo = 0; glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kQuadIndices), kQuadIndices, GL_STATIC_DRAW); - static constexpr const char* kVertexShaderSource = R"(#version 330 core +static constexpr const char* kVertexShaderSource = R"(#version 330 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec3 aColor; +out vec3 vColor; void main() { - const vec2 kPositions[4] = vec2[]( - vec2(-0.6, -0.6), - vec2( 0.6, -0.6), - vec2( 0.6, 0.6), - vec2(-0.6, 0.6) - ); - gl_Position = vec4(kPositions[gl_VertexID], 0.0, 1.0); + gl_Position = vec4(aPos, 0.0, 1.0); + vColor = aColor; })"; static constexpr const char* kFragmentShaderSource = R"(#version 330 core +in vec3 vColor; layout(location = 0) out vec4 outColor; void main() { - outColor = vec4(0.95, 0.85, 0.2, 1.0); + outColor = vec4(vColor, 1.0); })"; const GLuint vs = glCreateShader(GL_VERTEX_SHADER); @@ -199,6 +219,7 @@ void main() { } glDeleteProgram(program); + glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ebo); glDeleteVertexArrays(1, &vao);