mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Refactor] (MG_Backend/DirectVulkan): get rid of junk, and rename some symbols
This commit is contained in:
+1
-1
@@ -223,7 +223,7 @@ set(SOURCE_FILES
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/UniformDescriptorBinder.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/UniformManager.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/BufferArena.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferManager.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateBuilder.cpp
|
||||
|
||||
+31
-41
@@ -6,7 +6,7 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
// End of Source File Header
|
||||
|
||||
#include "UniformDescriptorBinder.h"
|
||||
#include "UniformManager.h"
|
||||
|
||||
#include "MG_State/GLState/Core.h"
|
||||
#include "MG_State/GLState/ProgramState/ProgramObject.h"
|
||||
@@ -53,7 +53,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::Initialize(VkDevice device, VkBufferManager* bufferManager,
|
||||
Bool UniformManager::Initialize(VkDevice device, VkBufferManager* bufferManager,
|
||||
ProgramFactory* programFactory,
|
||||
VkDeviceSize minUniformBufferOffsetAlignment, Uint32 frameCount,
|
||||
Uint32 maxBindings, Uint32 setsPerFrame,
|
||||
@@ -106,7 +106,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return true;
|
||||
}
|
||||
|
||||
void UniformDescriptorBinder::Shutdown() {
|
||||
void UniformManager::Shutdown() {
|
||||
for (auto& frame : m_frames) {
|
||||
if (m_device != VK_NULL_HANDLE) {
|
||||
for (auto& bucket : frame.descriptorPools) {
|
||||
@@ -135,7 +135,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
m_samplerManager = nullptr;
|
||||
}
|
||||
|
||||
void UniformDescriptorBinder::BeginFrame(Uint32 frameIndex) {
|
||||
void UniformManager::BeginFrame(Uint32 frameIndex) {
|
||||
MOBILEGL_ASSERT(frameIndex < m_frames.size(), "UniformDescriptorBinder::BeginFrame invalid frame index");
|
||||
auto& frame = m_frames[frameIndex];
|
||||
if (frame.peakAllocatedSetsThisFrame > m_peakDescriptorSetsObserved) {
|
||||
@@ -157,7 +157,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::ResolveSamplerDescriptor(VkCommandBuffer commandBuffer,
|
||||
Bool UniformManager::ResolveSamplerDescriptor(VkCommandBuffer commandBuffer,
|
||||
const MG_State::GLState::ProgramObject& program,
|
||||
const ProgramFactory::VkProgramLayout& layout,
|
||||
Uint32 binding, VkDescriptorImageInfo& outImageInfo) const {
|
||||
@@ -214,7 +214,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return outImageInfo.sampler != VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::ResolveSamplerDescriptorOverride(
|
||||
Bool UniformManager::ResolveSamplerDescriptorOverride(
|
||||
const SamplerBindingOverride& samplerBindingOverride, VkDescriptorImageInfo& outImageInfo) const {
|
||||
MOBILEGL_ASSERT(m_textureManager != nullptr, "ResolveSamplerDescriptorOverride: texture manager is null");
|
||||
MOBILEGL_ASSERT(m_samplerManager != nullptr, "ResolveSamplerDescriptorOverride: sampler manager is null");
|
||||
@@ -235,7 +235,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return outImageInfo.sampler != VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::ResolveSamplerTexture(const MG_State::GLState::ProgramObject& program,
|
||||
Bool UniformManager::ResolveSamplerTexture(const MG_State::GLState::ProgramObject& program,
|
||||
const ProgramFactory::VkProgramLayout& layout, Uint32 binding,
|
||||
SharedPtr<MG_State::GLState::ITextureObject>& outTexture) const {
|
||||
outTexture.reset();
|
||||
@@ -259,7 +259,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return outTexture != nullptr;
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::CollectSampledTextures(const MG_State::GLState::ProgramObject& program,
|
||||
Bool UniformManager::CollectSampledTextures(const MG_State::GLState::ProgramObject& program,
|
||||
Vector<MG_State::GLState::ITextureObject*>& outTextures) {
|
||||
outTextures.clear();
|
||||
MOBILEGL_ASSERT(m_programFactory != nullptr, "CollectSampledTextures: program factory is null");
|
||||
@@ -288,7 +288,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::GatherBindingPayloads(const MG_State::GLState::ProgramObject& program,
|
||||
Bool UniformManager::GatherBindingPayloads(const MG_State::GLState::ProgramObject& program,
|
||||
Vector<const void*>& outData,
|
||||
Vector<VkDeviceSize>& outSizes) const {
|
||||
outData.assign(m_maxBindings, nullptr);
|
||||
@@ -347,7 +347,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::CreateDescriptorPool(Uint32 maxSets, VkDescriptorPool& outPool) const {
|
||||
Bool UniformManager::CreateDescriptorPool(Uint32 maxSets, VkDescriptorPool& outPool) const {
|
||||
outPool = VK_NULL_HANDLE;
|
||||
if (m_device == VK_NULL_HANDLE || maxSets == 0 || m_maxBindings == 0) {
|
||||
return false;
|
||||
@@ -381,7 +381,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::GrowFrameDescriptorPool(FrameResources& frame, Uint32 frameIndex) {
|
||||
Bool UniformManager::GrowFrameDescriptorPool(FrameResources& frame, Uint32 frameIndex) {
|
||||
if (frame.descriptorPools.empty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -406,13 +406,26 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
||||
const MG_State::GLState::ProgramObject& program,
|
||||
Uint32 frameIndex) {
|
||||
return BindProgramUniformBuffers(commandBuffer, program, frameIndex, nullptr);
|
||||
VkResult UniformManager::AllocateDescriptorSetsFromActivePool(Uint32 frameIndex, const ProgramFactory::VkProgramLayout& layout, VkDescriptorSet& outDescriptorSet) {
|
||||
auto& frame = m_frames[frameIndex];
|
||||
auto& bucket = frame.descriptorPools[frame.activeDescriptorPoolIndex];
|
||||
VkDescriptorSetAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocInfo.descriptorSetCount = 1;
|
||||
allocInfo.pSetLayouts = &layout.descriptorSetLayout;
|
||||
|
||||
allocInfo.descriptorPool = bucket.handle;
|
||||
VkResult result = vkAllocateDescriptorSets(m_device, &allocInfo, &outDescriptorSet);
|
||||
if (result == VK_SUCCESS) {
|
||||
++bucket.allocatedSets;
|
||||
++frame.allocatedSetsThisFrame;
|
||||
frame.peakAllocatedSetsThisFrame =
|
||||
std::max(frame.peakAllocatedSetsThisFrame, frame.allocatedSetsThisFrame);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Bool UniformDescriptorBinder::BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
||||
Bool UniformManager::BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
||||
const MG_State::GLState::ProgramObject& program,
|
||||
Uint32 frameIndex,
|
||||
const SamplerBindingOverride* samplerBindingOverride) {
|
||||
@@ -430,32 +443,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
frame.activeDescriptorPoolIndex = 0;
|
||||
}
|
||||
|
||||
VkDescriptorSetAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocInfo.descriptorSetCount = 1;
|
||||
allocInfo.pSetLayouts = &layout->descriptorSetLayout;
|
||||
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
||||
|
||||
auto allocateFromActivePool = [&](VkResult& outResult) {
|
||||
auto& bucket = frame.descriptorPools[frame.activeDescriptorPoolIndex];
|
||||
allocInfo.descriptorPool = bucket.handle;
|
||||
outResult = vkAllocateDescriptorSets(m_device, &allocInfo, &descriptorSet);
|
||||
if (outResult == VK_SUCCESS) {
|
||||
++bucket.allocatedSets;
|
||||
++frame.allocatedSetsThisFrame;
|
||||
frame.peakAllocatedSetsThisFrame =
|
||||
std::max(frame.peakAllocatedSetsThisFrame, frame.allocatedSetsThisFrame);
|
||||
}
|
||||
};
|
||||
|
||||
VkResult allocResult = VK_SUCCESS;
|
||||
allocateFromActivePool(allocResult);
|
||||
VkResult allocResult = AllocateDescriptorSetsFromActivePool(frameIndex, *layout, descriptorSet);
|
||||
if (allocResult == VK_ERROR_OUT_OF_POOL_MEMORY || allocResult == VK_ERROR_FRAGMENTED_POOL) {
|
||||
if (!GrowFrameDescriptorPool(frame, frameIndex)) {
|
||||
MGLOG_E("UniformDescriptorBinder::BindProgramUniformBuffers failed: descriptor pool growth failed");
|
||||
return false;
|
||||
}
|
||||
allocateFromActivePool(allocResult);
|
||||
allocResult = AllocateDescriptorSetsFromActivePool(frameIndex, *layout, descriptorSet);
|
||||
}
|
||||
if (allocResult != VK_SUCCESS || descriptorSet == VK_NULL_HANDLE) {
|
||||
MGLOG_E("UniformDescriptorBinder::BindProgramUniformBuffers failed: vkAllocateDescriptorSets returned %d",
|
||||
@@ -470,7 +465,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const Uint8 kFallbackData[16] = {};
|
||||
MOBILEGL_ASSERT(m_textureManager != nullptr, "BindProgramUniformBuffers: texture manager is null");
|
||||
MOBILEGL_ASSERT(m_samplerManager != nullptr, "BindProgramUniformBuffers: sampler manager is null");
|
||||
MOBILEGL_ASSERT(m_bufferManager != nullptr, "BindProgramUniformBuffers: buffer manager is null");
|
||||
@@ -511,10 +505,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
payloadSize = globalUboSize;
|
||||
}
|
||||
}
|
||||
if (payload == nullptr || payloadSize == 0) {
|
||||
payload = kFallbackData;
|
||||
payloadSize = sizeof(kFallbackData);
|
||||
}
|
||||
}
|
||||
|
||||
BufferSlice slice{};
|
||||
+4
-4
@@ -22,7 +22,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
}
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
class UniformDescriptorBinder {
|
||||
class UniformManager {
|
||||
public:
|
||||
struct SamplerBindingOverride {
|
||||
Uint32 binding = 0;
|
||||
@@ -40,11 +40,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void BeginFrame(Uint32 frameIndex);
|
||||
Bool CollectSampledTextures(const MG_State::GLState::ProgramObject& program,
|
||||
Vector<MG_State::GLState::ITextureObject*>& outTextures);
|
||||
Bool BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
||||
const MG_State::GLState::ProgramObject& program, Uint32 frameIndex);
|
||||
Bool BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
||||
const MG_State::GLState::ProgramObject& program, Uint32 frameIndex,
|
||||
const SamplerBindingOverride* samplerBindingOverride);
|
||||
const SamplerBindingOverride* samplerBindingOverride = nullptr);
|
||||
|
||||
private:
|
||||
struct DescriptorPoolBucket {
|
||||
@@ -72,6 +70,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Vector<VkDeviceSize>& outSizes) const;
|
||||
Bool CreateDescriptorPool(Uint32 maxSets, VkDescriptorPool& outPool) const;
|
||||
Bool GrowFrameDescriptorPool(FrameResources& frame, Uint32 frameIndex);
|
||||
VkResult AllocateDescriptorSetsFromActivePool(
|
||||
Uint32 frameIndex, const ProgramFactory::VkProgramLayout& layout, VkDescriptorSet& outDescriptorSet);
|
||||
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
VkBufferManager* m_bufferManager = nullptr;
|
||||
@@ -351,9 +351,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
succeeded = InitializeBlitResources();
|
||||
MOBILEGL_ASSERT(succeeded, "Blit pipeline resource initialization failed.");
|
||||
|
||||
m_uniformDescriptorBinder = MakeUnique<UniformDescriptorBinder>();
|
||||
MOBILEGL_ASSERT(m_uniformDescriptorBinder != nullptr, "UniformDescriptorBinder creation failed.");
|
||||
succeeded = m_uniformDescriptorBinder->Initialize(
|
||||
m_uniformManager = MakeUnique<UniformManager>();
|
||||
MOBILEGL_ASSERT(m_uniformManager != nullptr, "UniformDescriptorBinder creation failed.");
|
||||
succeeded = m_uniformManager->Initialize(
|
||||
m_device, &m_bufferManager, m_programFactory.get(),
|
||||
m_physicalDevice.properties.limits.minUniformBufferOffsetAlignment, m_config.MaxFramesInFlight,
|
||||
kMaxProgramBindings, kDescriptorSetsPerFrame, m_textureManager.get(), m_samplerManager.get());
|
||||
@@ -389,9 +389,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
m_frameContext.Destroy(m_device, m_commandPool);
|
||||
|
||||
if (m_uniformDescriptorBinder) {
|
||||
m_uniformDescriptorBinder->Shutdown();
|
||||
m_uniformDescriptorBinder.reset();
|
||||
if (m_uniformManager) {
|
||||
m_uniformManager->Shutdown();
|
||||
m_uniformManager.reset();
|
||||
}
|
||||
m_programFactory.reset();
|
||||
|
||||
@@ -431,7 +431,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MGLOG_I("VulkanRenderer shut down completed");
|
||||
}
|
||||
|
||||
Bool VulkanRenderer::UploadAndBindVertexStreams(
|
||||
Bool VulkanRenderer::UploadAndBindVertexBuffers(
|
||||
VkCommandBuffer commandBuffer, const MG_State::GLState::VertexArrayObject& vao) {
|
||||
auto& vertexInputState = m_vertexInputStateFactory->GetOrCreateVertexInputState(vao);
|
||||
|
||||
@@ -661,7 +661,7 @@ void main() {
|
||||
VkPipeline VulkanRenderer::GetOrCreateBlitPipeline(const RenderPassEntry& renderPassEntry) {
|
||||
MOBILEGL_ASSERT(m_blitResources.program != nullptr, "GetOrCreateBlitPipeline: blit program is null");
|
||||
MOBILEGL_ASSERT(m_programFactory != nullptr, "GetOrCreateBlitPipeline: program factory is null");
|
||||
MOBILEGL_ASSERT(m_uniformDescriptorBinder != nullptr, "GetOrCreateBlitPipeline: descriptor binder is null");
|
||||
MOBILEGL_ASSERT(m_uniformManager != nullptr, "GetOrCreateBlitPipeline: descriptor binder is null");
|
||||
|
||||
static const VkPipelineVertexInputStateCreateInfo kEmptyVertexInputState {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
|
||||
@@ -760,7 +760,7 @@ void main() {
|
||||
// Begin command recording if not yet
|
||||
if (!frame.isCommandRecording) {
|
||||
m_frameContext.BeginCommandRecording();
|
||||
m_uniformDescriptorBinder->BeginFrame(m_frameContext.GetCurrentFrameIndex());
|
||||
m_uniformManager->BeginFrame(m_frameContext.GetCurrentFrameIndex());
|
||||
}
|
||||
|
||||
auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
||||
@@ -770,7 +770,7 @@ void main() {
|
||||
// without draws in between to give it a chance to materialize such clear.
|
||||
// Deal with this situation here.
|
||||
Vector<MG_State::GLState::ITextureObject*> sampledTextures;
|
||||
Bool hasSampledTextures = m_uniformDescriptorBinder->CollectSampledTextures(program, sampledTextures);
|
||||
Bool hasSampledTextures = m_uniformManager->CollectSampledTextures(program, sampledTextures);
|
||||
MOBILEGL_ASSERT(hasSampledTextures, "%s: CollectSampledTextures failed", __func__);
|
||||
MGLOG_D("SetupDraw: program=%u drawFbo=%u sampledTextureCount=%zu activeRenderPass=%s",
|
||||
program.GetExternalIndex(), drawFbo ? drawFbo->GetExternalIndex() : 0u, sampledTextures.size(),
|
||||
@@ -856,11 +856,11 @@ void main() {
|
||||
|
||||
vkCmdBindPipeline(frame.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
|
||||
m_uniformDescriptorBinder->BindProgramUniformBuffers(frame.commandBuffer, program,
|
||||
m_uniformManager->BindProgramUniformBuffers(frame.commandBuffer, program,
|
||||
m_frameContext.GetCurrentFrameIndex());
|
||||
|
||||
auto vtxUploadOk = UploadAndBindVertexStreams(frame.commandBuffer, vao);
|
||||
MOBILEGL_ASSERT(vtxUploadOk, "SetupDraw skipped: failed to upload vertex streams");
|
||||
auto vtxUploadOk = UploadAndBindVertexBuffers(frame.commandBuffer, vao);
|
||||
MOBILEGL_ASSERT(vtxUploadOk, "SetupDraw skipped: failed to upload vertex buffers");
|
||||
|
||||
if (aspects & DrawSetupAspect::IndexBuffer) {
|
||||
auto idxUploadOk = UploadAndBindIndexBuffer(frame, vao, pIndexBufferView);
|
||||
@@ -1080,13 +1080,13 @@ void main() {
|
||||
writeUniform(m_blitResources.surfaceTransformLocation, &blitUniformData.surfaceTransform,
|
||||
sizeof(blitUniformData.surfaceTransform));
|
||||
|
||||
const auto samplerBindingOverride = UniformDescriptorBinder::SamplerBindingOverride{
|
||||
const auto samplerBindingOverride = UniformManager::SamplerBindingOverride{
|
||||
.binding = m_blitResources.samplerBinding,
|
||||
.texture = sourceTexture.get(),
|
||||
.sampler = (filter == GL_LINEAR ? m_blitResources.linearSampler.get()
|
||||
: m_blitResources.nearestSampler.get()),
|
||||
};
|
||||
const Bool bound = m_uniformDescriptorBinder->BindProgramUniformBuffers(
|
||||
const Bool bound = m_uniformManager->BindProgramUniformBuffers(
|
||||
frame.commandBuffer, *m_blitResources.program, m_frameContext.GetCurrentFrameIndex(),
|
||||
&samplerBindingOverride);
|
||||
MOBILEGL_ASSERT(bound, "TryBlitToDefaultFramebufferWithShader: BindProgramUniformBuffers failed");
|
||||
@@ -1118,7 +1118,7 @@ void main() {
|
||||
auto& frame = m_frameContext.GetCurrent();
|
||||
if (!frame.isCommandRecording) {
|
||||
m_frameContext.BeginCommandRecording();
|
||||
m_uniformDescriptorBinder->BeginFrame(m_frameContext.GetCurrentFrameIndex());
|
||||
m_uniformManager->BeginFrame(m_frameContext.GetCurrentFrameIndex());
|
||||
}
|
||||
|
||||
auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "PipelineFactory.h"
|
||||
#include "ProgramFactory.h"
|
||||
#include "SwapchainObject.h"
|
||||
#include "UniformDescriptorBinder.h"
|
||||
#include "UniformManager.h"
|
||||
#include "VertexInputStateFactory.h"
|
||||
#include "VkBufferObject.h"
|
||||
#include "VkBufferManager.h"
|
||||
@@ -180,7 +180,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
UniquePtr<PipelineFactory> m_pipelineFactory;
|
||||
UniquePtr<ProgramFactory> m_programFactory;
|
||||
UniquePtr<UniformDescriptorBinder> m_uniformDescriptorBinder;
|
||||
UniquePtr<UniformManager> m_uniformManager;
|
||||
UniquePtr<VertexInputStateFactory> m_vertexInputStateFactory;
|
||||
UniquePtr<VkClearManager> m_clearManager;
|
||||
UniquePtr<VkRenderPassManager> m_renderPassManager;
|
||||
@@ -206,7 +206,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const MG_State::GLState::VertexArrayObject& vao,
|
||||
const RenderPassEntry& renderPassEntry);
|
||||
|
||||
Bool UploadAndBindVertexStreams(VkCommandBuffer commandBuffer, const MG_State::GLState::VertexArrayObject& vao);
|
||||
Bool UploadAndBindVertexBuffers(VkCommandBuffer commandBuffer, const MG_State::GLState::VertexArrayObject& vao);
|
||||
Bool UploadAndBindIndexBuffer(FrameContext::FrameData& frame,
|
||||
const MG_State::GLState::VertexArrayObject& vao,
|
||||
const IndexBufferView* pIndexBufferView = nullptr);
|
||||
|
||||
Reference in New Issue
Block a user