Files
LibretroAdmin 12d6192054 Pool Vulkan objects and vertex loaders; no play allocations
Common/ObjectPool.c (C89) keeps objects of one class in chunks, the first
made at backend start: a freed object is pushed on a lock-free stack, an
allocation takes the stack whole (an exchange, so no ABA) and pushes the
rest back, or else takes the chunks' next slot. A pool destroyed with
objects still out is freed with the last of them. Classes take it with
OBJECT_POOL_MEMBERS / OBJECT_POOL_DEFINE: VKPipeline, VKShader,
VKTexture, VKFramebuffer and the vertex loaders, which are now their
own bucket list nodes. Vulkan's descriptor pool and cleanup lists get
their first room at boot.

Play allocations: 58 to 1 on the core's thread, 172 to 1 on the compile
workers (both a first use).
2026-11-09 17:33:05 +01:00

148 lines
4.3 KiB
C++

// Copyright 2014 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "VideoCommon/VertexLoaderBase.h"
#include <bit>
#include "Common/CommonTypes.h"
#include "VideoCommon/VertexLoader.h"
#include "VideoCommon/VertexLoader_Color.h"
#include "VideoCommon/VertexLoader_Normal.h"
#include "VideoCommon/VertexLoader_Position.h"
#include "VideoCommon/VertexLoader_TextCoord.h"
#include "VideoCommon/VideoConfig.h"
#ifdef _M_X86_64
#include "VideoCommon/VertexLoaderX64.h"
#elif defined(_M_ARM_64)
#include "VideoCommon/VertexLoaderARM64.h"
#endif
u32 VertexLoaderBase::GetVertexSize(const TVtxDesc& vtx_desc, const VAT& vtx_attr)
{
u32 size = 0;
// Each enabled TexMatIdx adds one byte, as does PosMatIdx
size += std::popcount(vtx_desc.low.Hex & 0x1FF);
const u32 pos_size = VertexLoader_Position::GetSize(vtx_desc.low.Position, vtx_attr.g0.PosFormat,
vtx_attr.g0.PosElements);
size += pos_size;
const u32 norm_size =
VertexLoader_Normal::GetSize(vtx_desc.low.Normal, vtx_attr.g0.NormalFormat,
vtx_attr.g0.NormalElements, vtx_attr.g0.NormalIndex3);
size += norm_size;
for (u32 i = 0; i < vtx_desc.low.Color.Size(); i++)
{
const u32 color_size =
VertexLoader_Color::GetSize(vtx_desc.low.Color[i], vtx_attr.GetColorFormat(i));
size += color_size;
}
for (u32 i = 0; i < vtx_desc.high.TexCoord.Size(); i++)
{
const u32 tc_size = VertexLoader_TextCoord::GetSize(
vtx_desc.high.TexCoord[i], vtx_attr.GetTexFormat(i), vtx_attr.GetTexElements(i));
size += tc_size;
}
return size;
}
u32 VertexLoaderBase::GetVertexComponents(const TVtxDesc& vtx_desc, const VAT& vtx_attr)
{
u32 components = 0;
if (vtx_desc.low.PosMatIdx)
components |= VB_HAS_POSMTXIDX;
for (u32 i = 0; i < vtx_desc.low.TexMatIdx.Size(); i++)
{
if (vtx_desc.low.TexMatIdx[i])
components |= VB_HAS_TEXMTXIDX0 << i;
}
// Vertices always have positions; thus there is no VB_HAS_POS as it would always be set
if (vtx_desc.low.Normal != VertexComponentFormat::NotPresent)
{
components |= VB_HAS_NORMAL;
if (vtx_attr.g0.NormalElements == NormalComponentCount::NTB)
components |= VB_HAS_TANGENT | VB_HAS_BINORMAL;
}
for (u32 i = 0; i < vtx_desc.low.Color.Size(); i++)
{
if (vtx_desc.low.Color[i] != VertexComponentFormat::NotPresent)
components |= VB_HAS_COL0 << i;
}
for (u32 i = 0; i < vtx_desc.high.TexCoord.Size(); i++)
{
if (vtx_desc.high.TexCoord[i] != VertexComponentFormat::NotPresent)
components |= VB_HAS_UV0 << i;
}
return components;
}
VertexLoaderBase* VertexLoaderBase::CreateVertexLoader(const TVtxDesc& vtx_desc,
const VAT& vtx_attr)
{
#if defined(_M_X86_64)
if (g_ActiveConfig.vertex_loader_type != VertexLoaderType::Software)
return new VertexLoaderX64(vtx_desc, vtx_attr);
#elif defined(_M_ARM_64)
if (g_ActiveConfig.vertex_loader_type != VertexLoaderType::Software)
return new VertexLoaderARM64(vtx_desc, vtx_attr);
#endif
return new VertexLoader(vtx_desc, vtx_attr);
}
int VertexLoaderBase::RunVertices(const u8* src, u8* dst, int count)
{
#if defined(_M_X86_64)
if (m_jit)
return static_cast<VertexLoaderX64*>(this)->RunVertices(src, dst, count);
#elif defined(_M_ARM_64)
if (m_jit)
return static_cast<VertexLoaderARM64*>(this)->RunVertices(src, dst, count);
#endif
return static_cast<VertexLoader*>(this)->RunVertices(src, dst, count);
}
void VertexLoaderPoolsCreate()
{
#if defined(_M_X86_64)
VertexLoaderX64::CreatePool();
#elif defined(_M_ARM_64)
VertexLoaderARM64::CreatePool();
#endif
if (g_ActiveConfig.vertex_loader_type == VertexLoaderType::Software)
VertexLoader::CreatePool();
}
void VertexLoaderPoolsDestroy()
{
#if defined(_M_X86_64)
VertexLoaderX64::DestroyPool();
#elif defined(_M_ARM_64)
VertexLoaderARM64::DestroyPool();
#endif
VertexLoader::DestroyPool();
}
void VertexLoaderDelete(VertexLoaderBase* loader)
{
if (!loader)
return;
#if defined(_M_X86_64)
if (loader->m_jit)
{
delete static_cast<VertexLoaderX64*>(loader);
return;
}
#elif defined(_M_ARM_64)
if (loader->m_jit)
{
delete static_cast<VertexLoaderARM64*>(loader);
return;
}
#endif
delete static_cast<VertexLoader*>(loader);
}