Adds proper IBuffer usage instead of dynamic flag.

Comments By: phosit
Differential Revision: https://code.wildfiregames.com/D5281
This was SVN commit r28107.
This commit is contained in:
Vladislav Belov 2024-06-10 19:31:41 +00:00
parent 06545f5de1
commit b9fd6f18f0
32 changed files with 203 additions and 146 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -191,9 +191,10 @@ bool CMiniMapTexture::CellIconKeyEqual::operator()(
}
CMiniMapTexture::CMiniMapTexture(Renderer::Backend::IDevice* device, CSimulation2& simulation)
: m_Simulation(simulation), m_IndexArray(false),
m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX, true),
m_InstanceVertexArray(Renderer::Backend::IBuffer::Type::VERTEX, false)
: m_Simulation(simulation), m_IndexArray(Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::DYNAMIC | Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_InstanceVertexArray(Renderer::Backend::IBuffer::Type::VERTEX, Renderer::Backend::IBuffer::Usage::TRANSFER_DST)
{
// Register Relax NG validator.
CXeromyces::AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng");

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -32,8 +32,9 @@
CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
m_Type(type), m_Active(true), m_NextParticleIdx(0), m_EmissionRoundingError(0.f),
m_LastUpdateTime(type->m_Manager.GetCurrentTime()),
m_IndexArray(false),
m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX, true),
m_IndexArray(Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::DYNAMIC | Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_LastFrameNumber(-1)
{
// If we should start with particles fully emitted, pretend that we

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -325,7 +325,8 @@ void CDecalRData::BuildVertexData()
{
m_VBDecals = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SDecalVertex), vertices.size(),
Renderer::Backend::IBuffer::Type::VERTEX, false);
Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST);
}
m_VBDecals->m_Owner->UpdateChunkVertices(m_VBDecals.Get(), vertices.data());
@ -367,7 +368,8 @@ void CDecalRData::BuildVertexData()
{
m_VBDecalsIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), indices.size(),
Renderer::Backend::IBuffer::Type::INDEX, false);
Renderer::Backend::IBuffer::Type::INDEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST);
}
m_VBDecalsIndices->m_Owner->UpdateChunkVertices(m_VBDecalsIndices.Get(), indices.data());
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -59,8 +59,9 @@ struct ShaderModelDef : public CModelDefRPrivate
ShaderModelDef::ShaderModelDef(const CModelDefPtr& mdef)
: m_IndexArray(false),
m_Array(Renderer::Backend::IBuffer::Type::VERTEX, false)
: m_IndexArray(Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_Array(Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST)
{
size_t numVertices = mdef->GetNumVertices();
@ -127,7 +128,8 @@ struct ShaderModel : public CModelRData
ShaderModel(const void* key)
: CModelRData(key),
m_Array(Renderer::Backend::IBuffer::Type::VERTEX, true)
m_Array(Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::DYNAMIC | Renderer::Backend::IBuffer::Usage::TRANSFER_DST)
{}
};

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -58,7 +58,8 @@ struct IModelDef : public CModelDefRPrivate
IModelDef::IModelDef(const CModelDefPtr& mdef, bool gpuSkinning, bool calculateTangents)
: m_IndexArray(false), m_Array(Renderer::Backend::IBuffer::Type::VERTEX, false)
: m_IndexArray(Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_Array(Renderer::Backend::IBuffer::Type::VERTEX, Renderer::Backend::IBuffer::Usage::TRANSFER_DST)
{
size_t numVertices = mdef->GetNumVertices();

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -213,8 +213,9 @@ struct OverlayRendererInternals
const float OverlayRenderer::OVERLAY_VOFFSET = 0.2f;
OverlayRendererInternals::OverlayRendererInternals()
: quadVertices(Renderer::Backend::IBuffer::Type::VERTEX, true),
quadIndices(false)
: quadVertices(Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::DYNAMIC | Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
quadIndices(Renderer::Backend::IBuffer::Usage::TRANSFER_DST)
{
quadAttributePos.format = Renderer::Backend::Format::R32G32B32_SFLOAT;
quadVertices.AddAttribute(&quadAttributePos);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -422,7 +422,8 @@ void CPatchRData::BuildBlends()
m_VBBlends = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SBlendVertex), blendVertices.size(),
Renderer::Backend::IBuffer::Type::VERTEX, false,
Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::TERRAIN);
m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends.Get(), &blendVertices[0]);
@ -432,7 +433,8 @@ void CPatchRData::BuildBlends()
m_VBBlendIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), blendIndices.size(),
Renderer::Backend::IBuffer::Type::INDEX, false,
Renderer::Backend::IBuffer::Type::INDEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::TERRAIN);
m_VBBlendIndices->m_Owner->UpdateChunkVertices(m_VBBlendIndices.Get(), &blendIndices[0]);
}
@ -636,7 +638,8 @@ void CPatchRData::BuildIndices()
// Construct vertex buffer
m_VBBaseIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), indices.size(),
Renderer::Backend::IBuffer::Type::INDEX, false, nullptr, CVertexBufferManager::Group::TERRAIN);
Renderer::Backend::IBuffer::Type::INDEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST, nullptr, CVertexBufferManager::Group::TERRAIN);
m_VBBaseIndices->m_Owner->UpdateChunkVertices(m_VBBaseIndices.Get(), &indices[0]);
}
@ -682,7 +685,8 @@ void CPatchRData::BuildVertices()
{
m_VBBase = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SBaseVertex), vsize * vsize,
Renderer::Backend::IBuffer::Type::VERTEX, false,
Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::TERRAIN);
}
@ -776,7 +780,8 @@ void CPatchRData::BuildSides()
{
m_VBSides = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SSideVertex), sideVertices.size(),
Renderer::Backend::IBuffer::Type::VERTEX, false,
Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::DEFAULT);
}
m_VBSides->m_Owner->UpdateChunkVertices(m_VBSides.Get(), &sideVertices[0]);
@ -1538,13 +1543,15 @@ void CPatchRData::BuildWater()
{
m_VBWater = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SWaterVertex), water_vertex_data.size(),
Renderer::Backend::IBuffer::Type::VERTEX, false,
Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::WATER);
m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater.Get(), &water_vertex_data[0]);
m_VBWaterIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), water_indices.size(),
Renderer::Backend::IBuffer::Type::INDEX, false,
Renderer::Backend::IBuffer::Type::INDEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::WATER);
m_VBWaterIndices->m_Owner->UpdateChunkVertices(m_VBWaterIndices.Get(), &water_indices[0]);
}
@ -1553,14 +1560,16 @@ void CPatchRData::BuildWater()
{
m_VBWaterShore = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SWaterVertex), water_vertex_data_shore.size(),
Renderer::Backend::IBuffer::Type::VERTEX, false,
Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::WATER);
m_VBWaterShore->m_Owner->UpdateChunkVertices(m_VBWaterShore.Get(), &water_vertex_data_shore[0]);
// Construct indices buffer
m_VBWaterIndicesShore = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), water_indices_shore.size(),
Renderer::Backend::IBuffer::Type::INDEX, false,
Renderer::Backend::IBuffer::Type::INDEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::WATER);
m_VBWaterIndicesShore->m_Owner->UpdateChunkVertices(m_VBWaterIndicesShore.Get(), &water_indices_shore[0]);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -40,7 +40,8 @@
#include <algorithm>
SkyManager::SkyManager()
: m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX, false)
: m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST)
{
CFG_GET_VAL("showsky", m_SkyVisible);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -331,7 +331,8 @@ void CTexturedLineRData::Update(const SOverlayTexturedLine& line)
m_BoundingBox += vertex.m_Position;
m_VB = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SVertex), vertices.size(), Renderer::Backend::IBuffer::Type::VERTEX, false);
sizeof(SVertex), vertices.size(), Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST);
// Allocation might fail (e.g. due to too many vertices).
if (m_VB)
{
@ -342,7 +343,8 @@ void CTexturedLineRData::Update(const SOverlayTexturedLine& line)
indices[k] += static_cast<u16>(m_VB->m_Index);
m_VBIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), indices.size(), Renderer::Backend::IBuffer::Type::INDEX, false);
sizeof(u16), indices.size(), Renderer::Backend::IBuffer::Type::INDEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST);
if (m_VBIndices)
m_VBIndices->m_Owner->UpdateChunkVertices(m_VBIndices.Get(), &indices[0]);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -66,8 +66,8 @@ uint32_t GetAttributeSize(const Renderer::Backend::Format format)
} // anonymous namespace
VertexArray::VertexArray(
const Renderer::Backend::IBuffer::Type type, const bool dynamic)
: m_Type(type), m_Dynamic(dynamic)
const Renderer::Backend::IBuffer::Type type, const uint32_t usage)
: m_Type(type), m_Usage(usage)
{
m_NumberOfVertices = 0;
@ -271,7 +271,7 @@ void VertexArray::Upload()
if (!m_VB)
{
m_VB = g_Renderer.GetVertexBufferManager().AllocateChunk(
m_Stride, m_NumberOfVertices, m_Type, m_Dynamic, m_BackingStore);
m_Stride, m_NumberOfVertices, m_Type, m_Usage, m_BackingStore);
}
if (!m_VB)
@ -293,14 +293,14 @@ void VertexArray::UploadIfNeeded(
void VertexArray::FreeBackingStore()
{
// In streaming modes, the backing store must be retained
ENSURE(!CVertexBuffer::UseStreaming(m_Dynamic));
ENSURE(!CVertexBuffer::UseStreaming(m_Usage));
rtl_FreeAligned(m_BackingStore);
m_BackingStore = 0;
}
VertexIndexArray::VertexIndexArray(const bool dynamic) :
VertexArray(Renderer::Backend::IBuffer::Type::INDEX, dynamic)
VertexIndexArray::VertexIndexArray(const uint32_t usage) :
VertexArray(Renderer::Backend::IBuffer::Type::INDEX, usage)
{
m_Attr.format = Renderer::Backend::Format::R16_UINT;
AddAttribute(&m_Attr);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -160,7 +160,7 @@ public:
public:
VertexArray(
const Renderer::Backend::IBuffer::Type type, const bool dynamic);
const Renderer::Backend::IBuffer::Type type, const uint32_t usage);
~VertexArray();
// Set the number of vertices stored in the array
@ -203,7 +203,7 @@ private:
}
Renderer::Backend::IBuffer::Type m_Type;
bool m_Dynamic;
uint32_t m_Usage = 0;
size_t m_NumberOfVertices;
std::vector<Attribute*> m_Attributes;
@ -219,7 +219,7 @@ private:
class VertexIndexArray : public VertexArray
{
public:
VertexIndexArray(const bool dynamic);
VertexIndexArray(const uint32_t usage);
/// Gets the iterator over the (only) attribute in this array, i.e. a u16.
VertexArrayIterator<u16> GetIterator() const;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -36,14 +36,14 @@ constexpr std::size_t MAX_VB_SIZE_BYTES = 4 * 1024 * 1024;
CVertexBuffer::CVertexBuffer(
Renderer::Backend::IDevice* device, const char* name, const size_t vertexSize,
const Renderer::Backend::IBuffer::Type type, const bool dynamic)
: CVertexBuffer(device, name, vertexSize, type, dynamic, MAX_VB_SIZE_BYTES)
const Renderer::Backend::IBuffer::Type type, const uint32_t usage)
: CVertexBuffer(device, name, vertexSize, type, usage, MAX_VB_SIZE_BYTES)
{
}
CVertexBuffer::CVertexBuffer(
Renderer::Backend::IDevice* device, const char* name, const size_t vertexSize,
const Renderer::Backend::IBuffer::Type type, const bool dynamic,
const Renderer::Backend::IBuffer::Type type, const uint32_t usage,
const size_t maximumBufferSize)
: m_VertexSize(vertexSize), m_HasNeededChunks(false)
{
@ -65,7 +65,7 @@ CVertexBuffer::CVertexBuffer(
m_MaxVertices = m_FreeVertices = size / vertexSize;
m_Buffer = device->CreateBuffer(
name, type, m_MaxVertices * m_VertexSize, dynamic);
name, type, m_MaxVertices * m_VertexSize, usage);
// create sole free chunk
VBChunk* chunk = new VBChunk;
@ -88,10 +88,10 @@ CVertexBuffer::~CVertexBuffer()
bool CVertexBuffer::CompatibleVertexType(
const size_t vertexSize, const Renderer::Backend::IBuffer::Type type,
const bool dynamic) const
const uint32_t usage) const
{
ENSURE(m_Buffer);
return type == m_Buffer->GetType() && dynamic == m_Buffer->IsDynamic() && vertexSize == m_VertexSize;
return type == m_Buffer->GetType() && usage == m_Buffer->GetUsage() && vertexSize == m_VertexSize;
}
///////////////////////////////////////////////////////////////////////////////
@ -100,14 +100,14 @@ bool CVertexBuffer::CompatibleVertexType(
// if no free chunks available
CVertexBuffer::VBChunk* CVertexBuffer::Allocate(
const size_t vertexSize, const size_t numberOfVertices,
const Renderer::Backend::IBuffer::Type type, const bool dynamic,
const Renderer::Backend::IBuffer::Type type, const uint32_t usage,
void* backingStore)
{
// check this is the right kind of buffer
if (!CompatibleVertexType(vertexSize, type, dynamic))
if (!CompatibleVertexType(vertexSize, type, usage))
return nullptr;
if (UseStreaming(dynamic))
if (UseStreaming(usage))
ENSURE(backingStore != nullptr);
// quick check there's enough vertices spare to allocate
@ -206,7 +206,7 @@ void CVertexBuffer::Release(VBChunk* chunk)
void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk, void* data)
{
ENSURE(m_Buffer);
if (UseStreaming(m_Buffer->IsDynamic()))
if (UseStreaming(m_Buffer->GetUsage()))
{
// The backend buffer is now out of sync with the backing store.
chunk->m_Dirty = true;
@ -226,7 +226,7 @@ void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk, void* data)
void CVertexBuffer::UploadIfNeeded(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (UseStreaming(m_Buffer->IsDynamic()))
if (UseStreaming(m_Buffer->GetUsage()))
{
if (!m_HasNeededChunks)
return;
@ -310,9 +310,9 @@ void CVertexBuffer::DumpStatus() const
debug_printf("max size = %d\n", static_cast<int>(maxSize));
}
bool CVertexBuffer::UseStreaming(const bool dynamic)
bool CVertexBuffer::UseStreaming(const uint32_t usage)
{
return dynamic;
return usage & Renderer::Backend::IBuffer::Usage::DYNAMIC;
}
void CVertexBuffer::PrepareForRendering(VBChunk* chunk)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -93,11 +93,11 @@ public:
CVertexBuffer(
Renderer::Backend::IDevice* device,
const char* name, const size_t vertexSize,
const Renderer::Backend::IBuffer::Type type, const bool dynamic);
const Renderer::Backend::IBuffer::Type type, const uint32_t usage);
CVertexBuffer(
Renderer::Backend::IDevice* device,
const char* name, const size_t vertexSize,
const Renderer::Backend::IBuffer::Type type, const bool dynamic,
const Renderer::Backend::IBuffer::Type type, const uint32_t usage,
const size_t maximumBufferSize);
~CVertexBuffer();
@ -116,7 +116,7 @@ public:
/// Returns true if this vertex buffer is compatible with the specified vertex type and intended usage.
bool CompatibleVertexType(
const size_t vertexSize, const Renderer::Backend::IBuffer::Type type,
const bool dynamic) const;
const uint32_t usage) const;
void DumpStatus() const;
@ -130,7 +130,7 @@ public:
* If false, we assume it will change rarely, and use direct upload to
* update it incrementally. The backing store can be freed to save memory.
*/
static bool UseStreaming(const bool dynamic);
static bool UseStreaming(const uint32_t usage);
Renderer::Backend::IBuffer* GetBuffer() { return m_Buffer.get(); }
@ -141,7 +141,7 @@ private:
/// and with the given type - return null if no free chunks available
VBChunk* Allocate(
const size_t vertexSize, const size_t numberOfVertices,
const Renderer::Backend::IBuffer::Type type, const bool dynamic,
const Renderer::Backend::IBuffer::Type type, const uint32_t usage,
void* backingStore);
/// Return given chunk to this buffer
void Release(VBChunk* chunk);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -112,14 +112,14 @@ void CVertexBufferManager::Handle::Reset()
CVertexBufferManager::Handle CVertexBufferManager::AllocateChunk(
const size_t vertexSize, const size_t numberOfVertices,
const Renderer::Backend::IBuffer::Type type,
const bool dynamic, void* backingStore, Group group)
const uint32_t usage, void* backingStore, Group group)
{
ENSURE(vertexSize > 0);
ENSURE(numberOfVertices > 0);
CVertexBuffer::VBChunk* result = nullptr;
if (CVertexBuffer::UseStreaming(dynamic))
if (CVertexBuffer::UseStreaming(usage))
ENSURE(backingStore != NULL);
// TODO, RC - run some sanity checks on allocation request
@ -130,7 +130,7 @@ CVertexBufferManager::Handle CVertexBufferManager::AllocateChunk(
debug_printf("\n============================\n# allocate vsize=%zu nverts=%zu\n\n", vertexSize, numVertices);
for (const std::unique_ptr<CVertexBuffer>& buffer : buffers)
{
if (buffer->CompatibleVertexType(vertexSize, type, dynamic))
if (buffer->CompatibleVertexType(vertexSize, type, usage))
{
debug_printf("%p\n", buffer.get());
buffer->DumpStatus();
@ -142,7 +142,7 @@ CVertexBufferManager::Handle CVertexBufferManager::AllocateChunk(
// satisfy the allocation
for (const std::unique_ptr<CVertexBuffer>& buffer : buffers)
{
result = buffer->Allocate(vertexSize, numberOfVertices, type, dynamic, backingStore);
result = buffer->Allocate(vertexSize, numberOfVertices, type, usage, backingStore);
if (result)
return Handle(result);
}
@ -150,15 +150,15 @@ CVertexBufferManager::Handle CVertexBufferManager::AllocateChunk(
char bufferName[64] = {0};
snprintf(
bufferName, std::size(bufferName), "%s (%s, %zu%s)",
GetBufferTypeName(type), GetGroupName(group), vertexSize, (dynamic ? ", dynamic" : ""));
GetBufferTypeName(type), GetGroupName(group), vertexSize, ((usage & Renderer::Backend::IBuffer::Usage::DYNAMIC) ? ", dynamic" : ""));
// got this far; need to allocate a new buffer
buffers.emplace_back(
group == Group::DEFAULT
? std::make_unique<CVertexBuffer>(m_Device, bufferName, vertexSize, type, dynamic)
? std::make_unique<CVertexBuffer>(m_Device, bufferName, vertexSize, type, usage)
// Reduces the buffer size for not so frequent buffers.
: std::make_unique<CVertexBuffer>(m_Device, bufferName, vertexSize, type, dynamic, 1024 * 1024));
result = buffers.back()->Allocate(vertexSize, numberOfVertices, type, dynamic, backingStore);
: std::make_unique<CVertexBuffer>(m_Device, bufferName, vertexSize, type, usage, 1024 * 1024));
result = buffers.back()->Allocate(vertexSize, numberOfVertices, type, usage, backingStore);
if (!result)
{

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -93,7 +93,7 @@ public:
Handle AllocateChunk(
const size_t vertexSize, const size_t numberOfVertices,
const Renderer::Backend::IBuffer::Type type,
const bool dynamic, void* backingStore = nullptr, Group group = Group::DEFAULT);
const uint32_t usage, void* backingStore = nullptr, Group group = Group::DEFAULT);
/// Returns the given @p chunk to its owning buffer
void Release(CVertexBuffer::VBChunk* chunk);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -649,7 +649,8 @@ void WaterManager::CreateWaveMeshes()
// Generic indexes, max-length
m_ShoreWavesVBIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), water_indices.size(),
Renderer::Backend::IBuffer::Type::INDEX, false,
Renderer::Backend::IBuffer::Type::INDEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::WATER);
m_ShoreWavesVBIndices->m_Owner->UpdateChunkVertices(m_ShoreWavesVBIndices.Get(), &water_indices[0]);
@ -878,7 +879,8 @@ void WaterManager::CreateWaveMeshes()
shoreWave->m_VBVertices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SWavesVertex), vertices.size(),
Renderer::Backend::IBuffer::Type::VERTEX, false,
Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST,
nullptr, CVertexBufferManager::Group::WATER);
shoreWave->m_VBVertices->m_Owner->UpdateChunkVertices(shoreWave->m_VBVertices.Get(), &vertices[0]);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -39,9 +39,20 @@ public:
UNIFORM,
};
// Using a struct instead of a enum allows using the same syntax while
// avoiding adding operator overrides and additional checks on casts.
struct Usage
{
static constexpr uint32_t DYNAMIC = 1u << 0u;
static constexpr uint32_t TRANSFER_SRC = 1u << 1u;
static constexpr uint32_t TRANSFER_DST = 1u << 2u;
};
virtual Type GetType() const = 0;
virtual uint32_t GetSize() const = 0;
virtual bool IsDynamic() const = 0;
virtual uint32_t GetUsage() const = 0;
bool IsDynamic() const { return GetUsage() & IBuffer::Usage::DYNAMIC; }
};
} // namespace Backend

View File

@ -122,7 +122,7 @@ public:
SDepthStencilAttachment* depthStencilAttachment) = 0;
virtual std::unique_ptr<IBuffer> CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic) = 0;
const char* name, const IBuffer::Type type, const uint32_t size, const uint32_t usage) = 0;
virtual std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) = 0;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -32,13 +32,13 @@ namespace Dummy
// static
std::unique_ptr<IBuffer> CBuffer::Create(
CDevice* device, const Type type, const uint32_t size, const bool dynamic)
CDevice* device, const Type type, const uint32_t size, const uint32_t usage)
{
std::unique_ptr<CBuffer> buffer(new CBuffer());
buffer->m_Device = device;
buffer->m_Type = type;
buffer->m_Size = size;
buffer->m_Dynamic = dynamic;
buffer->m_Usage = usage;
return buffer;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -42,13 +42,13 @@ public:
Type GetType() const override { return m_Type; }
uint32_t GetSize() const override { return m_Size; }
bool IsDynamic() const override { return m_Dynamic; }
uint32_t GetUsage() const override { return m_Usage; }
private:
friend class CDevice;
static std::unique_ptr<IBuffer> Create(
CDevice* device, const Type type, const uint32_t size, const bool dynamic);
CDevice* device, const Type type, const uint32_t size, const uint32_t usage);
CBuffer();
@ -56,7 +56,7 @@ private:
Type m_Type = Type::VERTEX;
uint32_t m_Size = 0;
bool m_Dynamic = false;
uint32_t m_Usage = 0;
};
} // namespace Dummy

View File

@ -116,9 +116,9 @@ std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
}
std::unique_ptr<IBuffer> CDevice::CreateBuffer(
const char*, const CBuffer::Type type, const uint32_t size, const bool dynamic)
const char*, const CBuffer::Type type, const uint32_t size, const uint32_t usage)
{
return CBuffer::Create(this, type, size, dynamic);
return CBuffer::Create(this, type, size, usage);
}
std::unique_ptr<IShaderProgram> CDevice::CreateShaderProgram(

View File

@ -79,7 +79,7 @@ public:
SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic) override;
const char* name, const IBuffer::Type type, const uint32_t size, const uint32_t usage) override;
std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) override;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -38,18 +38,18 @@ namespace GL
// static
std::unique_ptr<CBuffer> CBuffer::Create(
CDevice* device, const char* name,
const Type type, const uint32_t size, const bool dynamic)
const Type type, const uint32_t size, const uint32_t usage)
{
ENSURE(type == Type::VERTEX || type == Type::INDEX);
std::unique_ptr<CBuffer> buffer(new CBuffer());
buffer->m_Device = device;
buffer->m_Type = type;
buffer->m_Size = size;
buffer->m_Dynamic = dynamic;
buffer->m_Usage = usage;
glGenBuffersARB(1, &buffer->m_Handle);
const GLenum target = type == Type::INDEX ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
glBindBufferARB(target, buffer->m_Handle);
glBufferDataARB(target, size, nullptr, dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
glBufferDataARB(target, size, nullptr, (usage & IBuffer::Usage::DYNAMIC) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
#if !CONFIG2_GLES
if (buffer->m_Device->GetCapabilities().debugLabels)
{

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -44,7 +44,7 @@ public:
Type GetType() const override { return m_Type; }
uint32_t GetSize() const override { return m_Size; }
bool IsDynamic() const override { return m_Dynamic; }
uint32_t GetUsage() const override { return m_Usage; }
GLuint GetHandle() { return m_Handle; }
@ -53,14 +53,14 @@ private:
static std::unique_ptr<CBuffer> Create(
CDevice* device, const char* name,
const Type type, const uint32_t size, const bool dynamic);
const Type type, const uint32_t size, const uint32_t usage);
CBuffer();
CDevice* m_Device = nullptr;
Type m_Type = Type::VERTEX;
uint32_t m_Size = 0;
bool m_Dynamic = false;
uint32_t m_Usage = 0;
GLuint m_Handle = 0;
};

View File

@ -904,9 +904,9 @@ std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
}
std::unique_ptr<IBuffer> CDevice::CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic)
const char* name, const IBuffer::Type type, const uint32_t size, const uint32_t usage)
{
return CBuffer::Create(this, name, type, size, dynamic);
return CBuffer::Create(this, name, type, size, usage);
}
std::unique_ptr<IShaderProgram> CDevice::CreateShaderProgram(

View File

@ -94,7 +94,7 @@ public:
SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic) override;
const char* name, const IBuffer::Type type, const uint32_t size, const uint32_t usage) override;
std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) override;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -22,6 +22,8 @@
#include "renderer/backend/vulkan/Device.h"
#include "renderer/backend/vulkan/Utilities.h"
#include <tuple>
namespace Renderer
{
@ -31,47 +33,69 @@ namespace Backend
namespace Vulkan
{
VkBufferUsageFlags ToVkBufferUsageFlags(const uint32_t usage)
{
VkBufferUsageFlags usageFlags = 0;
if (usage & IBuffer::Usage::TRANSFER_SRC)
usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
if (usage & IBuffer::Usage::TRANSFER_DST)
usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
return usageFlags;
}
std::tuple<VkBufferUsageFlags, VkMemoryPropertyFlags, VmaMemoryUsage> MakeCreationFlags(
const IBuffer::Type type, const uint32_t usage)
{
const VkBufferUsageFlags commonFlags = ToVkBufferUsageFlags(usage);
switch (type)
{
case IBuffer::Type::VERTEX:
ENSURE(usage & IBuffer::Usage::TRANSFER_DST);
return {
commonFlags | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE};
case IBuffer::Type::INDEX:
ENSURE(usage & IBuffer::Usage::TRANSFER_DST);
return {
commonFlags | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE};
case IBuffer::Type::UPLOAD:
ENSURE(usage & IBuffer::Usage::TRANSFER_SRC);
return {
0,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
VMA_MEMORY_USAGE_AUTO};
case IBuffer::Type::UNIFORM:
ENSURE(usage & IBuffer::Usage::TRANSFER_DST);
return {
commonFlags | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE};
}
return {0, 0, VMA_MEMORY_USAGE_AUTO};
}
// static
std::unique_ptr<CBuffer> CBuffer::Create(
CDevice* device, const char* name, const Type type, const uint32_t size,
const bool dynamic)
const uint32_t usage)
{
std::unique_ptr<CBuffer> buffer(new CBuffer());
buffer->m_Device = device;
buffer->m_Type = type;
buffer->m_Size = size;
buffer->m_Dynamic = dynamic;
buffer->m_Usage = usage;
VkMemoryPropertyFlags properties = 0;
VkBufferUsageFlags usage = VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM;
VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
switch (type)
{
case Type::VERTEX:
usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
memoryUsage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
break;
case Type::INDEX:
usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
memoryUsage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
break;
case Type::UPLOAD:
usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
break;
case Type::UNIFORM:
usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
memoryUsage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
break;
}
const auto [usageFlags, memoryProperties, memoryUsage] = MakeCreationFlags(type, usage);
VkBufferCreateInfo bufferCreateInfo{};
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferCreateInfo.size = size;
bufferCreateInfo.usage = usage;
bufferCreateInfo.usage = usageFlags;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo allocationCreateInfo{};
@ -81,7 +105,7 @@ std::unique_ptr<CBuffer> CBuffer::Create(
allocationCreateInfo.flags |= VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
allocationCreateInfo.pUserData = const_cast<char*>(name);
#endif
allocationCreateInfo.requiredFlags = properties;
allocationCreateInfo.requiredFlags = memoryProperties;
allocationCreateInfo.usage = memoryUsage;
const VkResult createBufferResult = vmaCreateBuffer(
device->GetVMAAllocator(), &bufferCreateInfo, &allocationCreateInfo,

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -44,7 +44,7 @@ public:
Type GetType() const override { return m_Type; }
uint32_t GetSize() const override { return m_Size; }
bool IsDynamic() const override { return m_Dynamic; }
uint32_t GetUsage() const override { return m_Usage; }
VkBuffer GetVkBuffer() { return m_Buffer; }
@ -58,7 +58,7 @@ private:
static std::unique_ptr<CBuffer> Create(
CDevice* device, const char* name, const Type type, const uint32_t size,
const bool dynamic);
const uint32_t usage);
CBuffer();
@ -66,7 +66,7 @@ private:
Type m_Type = Type::VERTEX;
uint32_t m_Size = 0;
bool m_Dynamic = false;
uint32_t m_Usage = 0;
VkBuffer m_Buffer = VK_NULL_HANDLE;
VmaAllocation m_Allocation = VK_NULL_HANDLE;

View File

@ -749,15 +749,15 @@ std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
}
std::unique_ptr<IBuffer> CDevice::CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic)
const char* name, const IBuffer::Type type, const uint32_t size, const uint32_t usage)
{
return CreateCBuffer(name, type, size, dynamic);
return CreateCBuffer(name, type, size, usage);
}
std::unique_ptr<CBuffer> CDevice::CreateCBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic)
const char* name, const IBuffer::Type type, const uint32_t size, const uint32_t usage)
{
return CBuffer::Create(this, name, type, size, dynamic);
return CBuffer::Create(this, name, type, size, usage);
}
std::unique_ptr<IShaderProgram> CDevice::CreateShaderProgram(

View File

@ -101,10 +101,10 @@ public:
SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic) override;
const char* name, const IBuffer::Type type, const uint32_t size, const uint32_t usage) override;
std::unique_ptr<CBuffer> CreateCBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic);
const char* name, const IBuffer::Type type, const uint32_t size, const uint32_t usage);
std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) override;

View File

@ -242,9 +242,9 @@ void CDeviceCommandContext::CUploadRing::ResizeIfNeeded(
m_Capacity = std::max(m_Capacity * 2, round_up_to_pow2(dataSize));
m_Buffer = m_Device->CreateCBuffer(
"UploadRingBuffer", m_Type, m_Capacity, true);
"UploadRingBuffer", m_Type, m_Capacity, IBuffer::Usage::DYNAMIC | IBuffer::Usage::TRANSFER_DST);
m_StagingBuffer = m_Device->CreateCBuffer(
"UploadRingStagingBuffer", IBuffer::Type::UPLOAD, NUMBER_OF_FRAMES_IN_FLIGHT * m_Capacity, true);
"UploadRingStagingBuffer", IBuffer::Type::UPLOAD, NUMBER_OF_FRAMES_IN_FLIGHT * m_Capacity, IBuffer::Usage::DYNAMIC | IBuffer::Usage::TRANSFER_SRC);
ENSURE(m_Buffer && m_StagingBuffer);
m_StagingBufferMappedData = static_cast<std::byte*>(m_StagingBuffer->GetMappedData());
ENSURE(m_StagingBufferMappedData);

View File

@ -356,7 +356,7 @@ uint32_t CRingCommandContext::AcquireFreeSpace(
std::max(m_StagingBuffer ? m_StagingBuffer->GetSize() * 2 : INITIAL_STAGING_BUFFER_CAPACITY, minimumRequiredCapacity),
m_MaxStagingBufferCapacity);
m_StagingBuffer = m_Device->CreateCBuffer(
"UploadRingBuffer", IBuffer::Type::UPLOAD, newCapacity, false);
"UploadRingBuffer", IBuffer::Type::UPLOAD, newCapacity, IBuffer::Usage::TRANSFER_SRC);
ENSURE(m_StagingBuffer);
m_StagingBufferFirst = 0;
m_StagingBufferCurrentFirst = 0;