mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (MG_Backend/DirectVulkan): vertex input state builder
This commit is contained in:
@@ -214,6 +214,7 @@ set(SOURCE_FILES
|
|||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/SwapchainObject.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/SwapchainObject.cpp
|
||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp
|
||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp
|
||||||
|
MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateBuilder.cpp
|
||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp
|
||||||
|
|
||||||
MobileGL/MG_State/GLState/Core.cpp
|
MobileGL/MG_State/GLState/Core.cpp
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
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");
|
||||||
|
|
||||||
if (first < 0) {
|
if (first < 0) {
|
||||||
MGLOG_W("DrawArrays skipped: first (%d) must be non-negative", first);
|
MGLOG_W("DrawArrays skipped: first (%d) must be non-negative", first);
|
||||||
@@ -105,7 +106,39 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pVulkanRenderer->DrawArrays(mode, first, count);
|
DrawArrayPayload payload{};
|
||||||
|
payload.mode = mode;
|
||||||
|
payload.first = first;
|
||||||
|
payload.count = count;
|
||||||
|
|
||||||
|
const auto vao = MG_State::pGLContext->GetBoundVertexArray();
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateBuilder.cpp
|
||||||
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||||
|
// Licensed under the GNU Lesser General Public License v3.0:
|
||||||
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
// End of Source File Header
|
||||||
|
|
||||||
|
#include "VertexInputStateBuilder.h"
|
||||||
|
|
||||||
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
VertexInputStateBuilder::VertexInputStateBuilder() {
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexInputStateBuilder::Reset() {
|
||||||
|
m_bindings.clear();
|
||||||
|
m_attributes.clear();
|
||||||
|
|
||||||
|
m_state = {};
|
||||||
|
m_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
m_state.vertexBindingDescriptionCount = 0;
|
||||||
|
m_state.pVertexBindingDescriptions = nullptr;
|
||||||
|
m_state.vertexAttributeDescriptionCount = 0;
|
||||||
|
m_state.pVertexAttributeDescriptions = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexInputStateBuilder& VertexInputStateBuilder::AddBinding(
|
||||||
|
Uint32 binding, Uint32 stride, VkVertexInputRate inputRate) {
|
||||||
|
VkVertexInputBindingDescription desc{};
|
||||||
|
desc.binding = binding;
|
||||||
|
desc.stride = stride;
|
||||||
|
desc.inputRate = inputRate;
|
||||||
|
m_bindings.push_back(desc);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexInputStateBuilder& VertexInputStateBuilder::AddAttribute(
|
||||||
|
Uint32 location, Uint32 binding, VkFormat format, Uint32 offset) {
|
||||||
|
VkVertexInputAttributeDescription desc{};
|
||||||
|
desc.location = location;
|
||||||
|
desc.binding = binding;
|
||||||
|
desc.format = format;
|
||||||
|
desc.offset = offset;
|
||||||
|
m_attributes.push_back(desc);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VkPipelineVertexInputStateCreateInfo& VertexInputStateBuilder::Build() {
|
||||||
|
m_state.vertexBindingDescriptionCount = static_cast<Uint32>(m_bindings.size());
|
||||||
|
m_state.pVertexBindingDescriptions = m_bindings.empty() ? nullptr : m_bindings.data();
|
||||||
|
m_state.vertexAttributeDescriptionCount = static_cast<Uint32>(m_attributes.size());
|
||||||
|
m_state.pVertexAttributeDescriptions = m_attributes.empty() ? nullptr : m_attributes.data();
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateBuilder.h
|
||||||
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||||
|
// Licensed under the GNU Lesser General Public License v3.0:
|
||||||
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
// End of Source File Header
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <Includes.h>
|
||||||
|
|
||||||
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
class VertexInputStateBuilder {
|
||||||
|
public:
|
||||||
|
VertexInputStateBuilder();
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
VertexInputStateBuilder& AddBinding(
|
||||||
|
Uint32 binding, Uint32 stride, VkVertexInputRate inputRate = VK_VERTEX_INPUT_RATE_VERTEX);
|
||||||
|
VertexInputStateBuilder& AddAttribute(Uint32 location, Uint32 binding, VkFormat format, Uint32 offset);
|
||||||
|
|
||||||
|
const VkPipelineVertexInputStateCreateInfo& Build();
|
||||||
|
|
||||||
|
private:
|
||||||
|
VkPipelineVertexInputStateCreateInfo m_state{};
|
||||||
|
Vector<VkVertexInputBindingDescription> m_bindings;
|
||||||
|
Vector<VkVertexInputAttributeDescription> m_attributes;
|
||||||
|
};
|
||||||
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
// End of Source File Header
|
// End of Source File Header
|
||||||
|
|
||||||
#include "VulkanRenderer.h"
|
#include "VulkanRenderer.h"
|
||||||
|
#include "VertexInputStateBuilder.h"
|
||||||
|
|
||||||
#include "MG_State/GLState/ProgramState/ProgramObject.h"
|
#include "MG_State/GLState/ProgramState/ProgramObject.h"
|
||||||
|
|
||||||
@@ -112,9 +113,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
dynamicState.dynamicStateCount = static_cast<uint32_t>(std::size(s_dynamicStates));
|
dynamicState.dynamicStateCount = static_cast<uint32_t>(std::size(s_dynamicStates));
|
||||||
dynamicState.pDynamicStates = s_dynamicStates;
|
dynamicState.pDynamicStates = s_dynamicStates;
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInput{VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO};
|
VertexInputStateBuilder vertexInputBuilder;
|
||||||
vertexInput.vertexBindingDescriptionCount = 0;
|
const auto& vertexInput = vertexInputBuilder.Build();
|
||||||
vertexInput.vertexAttributeDescriptionCount = 0;
|
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo ia{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
|
VkPipelineInputAssemblyStateCreateInfo ia{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
|
||||||
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
@@ -444,7 +444,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_frameContext.EndCommandRecording();
|
m_frameContext.EndCommandRecording();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::DrawArrays(GLenum mode, GLint first, GLsizei count) {
|
void VulkanRenderer::DrawArrays(const DrawArrayPayload& payload) {
|
||||||
|
if (payload.mode != GL_TRIANGLES) {
|
||||||
|
MGLOG_W("DrawArrays skipped: primitive mode %u is not supported yet", payload.mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EnsureFrameRecordingStarted();
|
EnsureFrameRecordingStarted();
|
||||||
auto& frame = m_frameContext.GetCurrent();
|
auto& frame = m_frameContext.GetCurrent();
|
||||||
if (!frame.isCommandRecording || !m_isMainRenderPassActive) {
|
if (!frame.isCommandRecording || !m_isMainRenderPassActive) {
|
||||||
@@ -471,7 +476,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
scissor.extent = swapchainExtent;
|
scissor.extent = swapchainExtent;
|
||||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdDraw(commandBuffer, static_cast<Uint32>(count), 1, static_cast<Uint32>(first), 0);
|
vkCmdDraw(commandBuffer, static_cast<Uint32>(payload.count), 1, static_cast<Uint32>(payload.first), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::DrawElements(GLenum type, GLsizei count, const void* indexData, SizeT indexDataSizeBytes) {
|
void VulkanRenderer::DrawElements(GLenum type, GLsizei count, const void* indexData, SizeT indexDataSizeBytes) {
|
||||||
|
|||||||
@@ -19,6 +19,20 @@
|
|||||||
#include "../VkIncludes.h"
|
#include "../VkIncludes.h"
|
||||||
|
|
||||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
struct DrawArrayPayload {
|
||||||
|
GLenum mode = GL_TRIANGLES;
|
||||||
|
GLint first = 0;
|
||||||
|
GLsizei count = 0;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
class VulkanRenderer {
|
class VulkanRenderer {
|
||||||
public:
|
public:
|
||||||
VulkanRenderer(NativeWindowType window, const VulkanRendererConfig& cfg = {});
|
VulkanRenderer(NativeWindowType window, const VulkanRendererConfig& cfg = {});
|
||||||
@@ -30,7 +44,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void RequestClear(GLbitfield mask, const FloatVec4& color, Float depth, Uint32 stencil);
|
void RequestClear(GLbitfield mask, const FloatVec4& color, Float depth, Uint32 stencil);
|
||||||
Bool ConsumePendingColorClear(VkClearColorValue& outClearColor);
|
Bool ConsumePendingColorClear(VkClearColorValue& outClearColor);
|
||||||
void EnsureFrameRecordingStarted();
|
void EnsureFrameRecordingStarted();
|
||||||
void DrawArrays(GLenum mode, GLint first, GLsizei count);
|
void DrawArrays(const DrawArrayPayload& payload);
|
||||||
void DrawElements(GLenum type, GLsizei count, const void* indexData, SizeT indexDataSizeBytes);
|
void DrawElements(GLenum type, GLsizei count, const void* indexData, SizeT indexDataSizeBytes);
|
||||||
void Render();
|
void Render();
|
||||||
void Present();
|
void Present();
|
||||||
|
|||||||
Reference in New Issue
Block a user