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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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) CMiniMapTexture::CMiniMapTexture(Renderer::Backend::IDevice* device, CSimulation2& simulation)
: m_Simulation(simulation), m_IndexArray(false), : m_Simulation(simulation), m_IndexArray(Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX, true), m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX,
m_InstanceVertexArray(Renderer::Backend::IBuffer::Type::VERTEX, false) 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. // Register Relax NG validator.
CXeromyces::AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng"); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -32,8 +32,9 @@
CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) : CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
m_Type(type), m_Active(true), m_NextParticleIdx(0), m_EmissionRoundingError(0.f), m_Type(type), m_Active(true), m_NextParticleIdx(0), m_EmissionRoundingError(0.f),
m_LastUpdateTime(type->m_Manager.GetCurrentTime()), m_LastUpdateTime(type->m_Manager.GetCurrentTime()),
m_IndexArray(false), m_IndexArray(Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX, true), m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::DYNAMIC | Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_LastFrameNumber(-1) m_LastFrameNumber(-1)
{ {
// If we should start with particles fully emitted, pretend that we // 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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( m_VBDecals = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SDecalVertex), vertices.size(), 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()); m_VBDecals->m_Owner->UpdateChunkVertices(m_VBDecals.Get(), vertices.data());
@ -367,7 +368,8 @@ void CDecalRData::BuildVertexData()
{ {
m_VBDecalsIndices = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBDecalsIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), indices.size(), 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()); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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) ShaderModelDef::ShaderModelDef(const CModelDefPtr& mdef)
: m_IndexArray(false), : m_IndexArray(Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
m_Array(Renderer::Backend::IBuffer::Type::VERTEX, false) m_Array(Renderer::Backend::IBuffer::Type::VERTEX,
Renderer::Backend::IBuffer::Usage::TRANSFER_DST)
{ {
size_t numVertices = mdef->GetNumVertices(); size_t numVertices = mdef->GetNumVertices();
@ -127,7 +128,8 @@ struct ShaderModel : public CModelRData
ShaderModel(const void* key) ShaderModel(const void* key)
: CModelRData(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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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) 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(); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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; const float OverlayRenderer::OVERLAY_VOFFSET = 0.2f;
OverlayRendererInternals::OverlayRendererInternals() OverlayRendererInternals::OverlayRendererInternals()
: quadVertices(Renderer::Backend::IBuffer::Type::VERTEX, true), : quadVertices(Renderer::Backend::IBuffer::Type::VERTEX,
quadIndices(false) 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; quadAttributePos.format = Renderer::Backend::Format::R32G32B32_SFLOAT;
quadVertices.AddAttribute(&quadAttributePos); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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( m_VBBlends = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SBlendVertex), blendVertices.size(), 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); nullptr, CVertexBufferManager::Group::TERRAIN);
m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends.Get(), &blendVertices[0]); m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends.Get(), &blendVertices[0]);
@ -432,7 +433,8 @@ void CPatchRData::BuildBlends()
m_VBBlendIndices = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBBlendIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), blendIndices.size(), 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); nullptr, CVertexBufferManager::Group::TERRAIN);
m_VBBlendIndices->m_Owner->UpdateChunkVertices(m_VBBlendIndices.Get(), &blendIndices[0]); m_VBBlendIndices->m_Owner->UpdateChunkVertices(m_VBBlendIndices.Get(), &blendIndices[0]);
} }
@ -636,7 +638,8 @@ void CPatchRData::BuildIndices()
// Construct vertex buffer // Construct vertex buffer
m_VBBaseIndices = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBBaseIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), indices.size(), 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]); m_VBBaseIndices->m_Owner->UpdateChunkVertices(m_VBBaseIndices.Get(), &indices[0]);
} }
@ -682,7 +685,8 @@ void CPatchRData::BuildVertices()
{ {
m_VBBase = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBBase = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SBaseVertex), vsize * vsize, 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); nullptr, CVertexBufferManager::Group::TERRAIN);
} }
@ -776,7 +780,8 @@ void CPatchRData::BuildSides()
{ {
m_VBSides = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBSides = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SSideVertex), sideVertices.size(), 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); nullptr, CVertexBufferManager::Group::DEFAULT);
} }
m_VBSides->m_Owner->UpdateChunkVertices(m_VBSides.Get(), &sideVertices[0]); m_VBSides->m_Owner->UpdateChunkVertices(m_VBSides.Get(), &sideVertices[0]);
@ -1538,13 +1543,15 @@ void CPatchRData::BuildWater()
{ {
m_VBWater = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBWater = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SWaterVertex), water_vertex_data.size(), 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); nullptr, CVertexBufferManager::Group::WATER);
m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater.Get(), &water_vertex_data[0]); m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater.Get(), &water_vertex_data[0]);
m_VBWaterIndices = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBWaterIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), water_indices.size(), 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); nullptr, CVertexBufferManager::Group::WATER);
m_VBWaterIndices->m_Owner->UpdateChunkVertices(m_VBWaterIndices.Get(), &water_indices[0]); m_VBWaterIndices->m_Owner->UpdateChunkVertices(m_VBWaterIndices.Get(), &water_indices[0]);
} }
@ -1553,14 +1560,16 @@ void CPatchRData::BuildWater()
{ {
m_VBWaterShore = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBWaterShore = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SWaterVertex), water_vertex_data_shore.size(), 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); nullptr, CVertexBufferManager::Group::WATER);
m_VBWaterShore->m_Owner->UpdateChunkVertices(m_VBWaterShore.Get(), &water_vertex_data_shore[0]); m_VBWaterShore->m_Owner->UpdateChunkVertices(m_VBWaterShore.Get(), &water_vertex_data_shore[0]);
// Construct indices buffer // Construct indices buffer
m_VBWaterIndicesShore = g_Renderer.GetVertexBufferManager().AllocateChunk( m_VBWaterIndicesShore = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), water_indices_shore.size(), 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); nullptr, CVertexBufferManager::Group::WATER);
m_VBWaterIndicesShore->m_Owner->UpdateChunkVertices(m_VBWaterIndicesShore.Get(), &water_indices_shore[0]); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -40,7 +40,8 @@
#include <algorithm> #include <algorithm>
SkyManager::SkyManager() 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); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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_BoundingBox += vertex.m_Position;
m_VB = g_Renderer.GetVertexBufferManager().AllocateChunk( 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). // Allocation might fail (e.g. due to too many vertices).
if (m_VB) if (m_VB)
{ {
@ -342,7 +343,8 @@ void CTexturedLineRData::Update(const SOverlayTexturedLine& line)
indices[k] += static_cast<u16>(m_VB->m_Index); indices[k] += static_cast<u16>(m_VB->m_Index);
m_VBIndices = g_Renderer.GetVertexBufferManager().AllocateChunk( 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) if (m_VBIndices)
m_VBIndices->m_Owner->UpdateChunkVertices(m_VBIndices.Get(), &indices[0]); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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 } // anonymous namespace
VertexArray::VertexArray( VertexArray::VertexArray(
const Renderer::Backend::IBuffer::Type type, const bool dynamic) const Renderer::Backend::IBuffer::Type type, const uint32_t usage)
: m_Type(type), m_Dynamic(dynamic) : m_Type(type), m_Usage(usage)
{ {
m_NumberOfVertices = 0; m_NumberOfVertices = 0;
@ -271,7 +271,7 @@ void VertexArray::Upload()
if (!m_VB) if (!m_VB)
{ {
m_VB = g_Renderer.GetVertexBufferManager().AllocateChunk( 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) if (!m_VB)
@ -293,14 +293,14 @@ void VertexArray::UploadIfNeeded(
void VertexArray::FreeBackingStore() void VertexArray::FreeBackingStore()
{ {
// In streaming modes, the backing store must be retained // In streaming modes, the backing store must be retained
ENSURE(!CVertexBuffer::UseStreaming(m_Dynamic)); ENSURE(!CVertexBuffer::UseStreaming(m_Usage));
rtl_FreeAligned(m_BackingStore); rtl_FreeAligned(m_BackingStore);
m_BackingStore = 0; m_BackingStore = 0;
} }
VertexIndexArray::VertexIndexArray(const bool dynamic) : VertexIndexArray::VertexIndexArray(const uint32_t usage) :
VertexArray(Renderer::Backend::IBuffer::Type::INDEX, dynamic) VertexArray(Renderer::Backend::IBuffer::Type::INDEX, usage)
{ {
m_Attr.format = Renderer::Backend::Format::R16_UINT; m_Attr.format = Renderer::Backend::Format::R16_UINT;
AddAttribute(&m_Attr); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -160,7 +160,7 @@ public:
public: public:
VertexArray( VertexArray(
const Renderer::Backend::IBuffer::Type type, const bool dynamic); const Renderer::Backend::IBuffer::Type type, const uint32_t usage);
~VertexArray(); ~VertexArray();
// Set the number of vertices stored in the array // Set the number of vertices stored in the array
@ -203,7 +203,7 @@ private:
} }
Renderer::Backend::IBuffer::Type m_Type; Renderer::Backend::IBuffer::Type m_Type;
bool m_Dynamic; uint32_t m_Usage = 0;
size_t m_NumberOfVertices; size_t m_NumberOfVertices;
std::vector<Attribute*> m_Attributes; std::vector<Attribute*> m_Attributes;
@ -219,7 +219,7 @@ private:
class VertexIndexArray : public VertexArray class VertexIndexArray : public VertexArray
{ {
public: public:
VertexIndexArray(const bool dynamic); VertexIndexArray(const uint32_t usage);
/// Gets the iterator over the (only) attribute in this array, i.e. a u16. /// Gets the iterator over the (only) attribute in this array, i.e. a u16.
VertexArrayIterator<u16> GetIterator() const; 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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( CVertexBuffer::CVertexBuffer(
Renderer::Backend::IDevice* device, const char* name, const size_t vertexSize, 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(device, name, vertexSize, type, dynamic, MAX_VB_SIZE_BYTES) : CVertexBuffer(device, name, vertexSize, type, usage, MAX_VB_SIZE_BYTES)
{ {
} }
CVertexBuffer::CVertexBuffer( CVertexBuffer::CVertexBuffer(
Renderer::Backend::IDevice* device, const char* name, const size_t vertexSize, 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) const size_t maximumBufferSize)
: m_VertexSize(vertexSize), m_HasNeededChunks(false) : m_VertexSize(vertexSize), m_HasNeededChunks(false)
{ {
@ -65,7 +65,7 @@ CVertexBuffer::CVertexBuffer(
m_MaxVertices = m_FreeVertices = size / vertexSize; m_MaxVertices = m_FreeVertices = size / vertexSize;
m_Buffer = device->CreateBuffer( m_Buffer = device->CreateBuffer(
name, type, m_MaxVertices * m_VertexSize, dynamic); name, type, m_MaxVertices * m_VertexSize, usage);
// create sole free chunk // create sole free chunk
VBChunk* chunk = new VBChunk; VBChunk* chunk = new VBChunk;
@ -88,10 +88,10 @@ CVertexBuffer::~CVertexBuffer()
bool CVertexBuffer::CompatibleVertexType( bool CVertexBuffer::CompatibleVertexType(
const size_t vertexSize, const Renderer::Backend::IBuffer::Type type, const size_t vertexSize, const Renderer::Backend::IBuffer::Type type,
const bool dynamic) const const uint32_t usage) const
{ {
ENSURE(m_Buffer); 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 // if no free chunks available
CVertexBuffer::VBChunk* CVertexBuffer::Allocate( CVertexBuffer::VBChunk* CVertexBuffer::Allocate(
const size_t vertexSize, const size_t numberOfVertices, 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) void* backingStore)
{ {
// check this is the right kind of buffer // check this is the right kind of buffer
if (!CompatibleVertexType(vertexSize, type, dynamic)) if (!CompatibleVertexType(vertexSize, type, usage))
return nullptr; return nullptr;
if (UseStreaming(dynamic)) if (UseStreaming(usage))
ENSURE(backingStore != nullptr); ENSURE(backingStore != nullptr);
// quick check there's enough vertices spare to allocate // 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) void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk, void* data)
{ {
ENSURE(m_Buffer); 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. // The backend buffer is now out of sync with the backing store.
chunk->m_Dirty = true; chunk->m_Dirty = true;
@ -226,7 +226,7 @@ void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk, void* data)
void CVertexBuffer::UploadIfNeeded( void CVertexBuffer::UploadIfNeeded(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext) Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{ {
if (UseStreaming(m_Buffer->IsDynamic())) if (UseStreaming(m_Buffer->GetUsage()))
{ {
if (!m_HasNeededChunks) if (!m_HasNeededChunks)
return; return;
@ -310,9 +310,9 @@ void CVertexBuffer::DumpStatus() const
debug_printf("max size = %d\n", static_cast<int>(maxSize)); 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) 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -93,11 +93,11 @@ public:
CVertexBuffer( CVertexBuffer(
Renderer::Backend::IDevice* device, Renderer::Backend::IDevice* device,
const char* name, const size_t vertexSize, 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( CVertexBuffer(
Renderer::Backend::IDevice* device, Renderer::Backend::IDevice* device,
const char* name, const size_t vertexSize, 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); const size_t maximumBufferSize);
~CVertexBuffer(); ~CVertexBuffer();
@ -116,7 +116,7 @@ public:
/// Returns true if this vertex buffer is compatible with the specified vertex type and intended usage. /// Returns true if this vertex buffer is compatible with the specified vertex type and intended usage.
bool CompatibleVertexType( bool CompatibleVertexType(
const size_t vertexSize, const Renderer::Backend::IBuffer::Type type, const size_t vertexSize, const Renderer::Backend::IBuffer::Type type,
const bool dynamic) const; const uint32_t usage) const;
void DumpStatus() const; void DumpStatus() const;
@ -130,7 +130,7 @@ public:
* If false, we assume it will change rarely, and use direct upload to * 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. * 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(); } 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 /// and with the given type - return null if no free chunks available
VBChunk* Allocate( VBChunk* Allocate(
const size_t vertexSize, const size_t numberOfVertices, 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); void* backingStore);
/// Return given chunk to this buffer /// Return given chunk to this buffer
void Release(VBChunk* chunk); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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( CVertexBufferManager::Handle CVertexBufferManager::AllocateChunk(
const size_t vertexSize, const size_t numberOfVertices, const size_t vertexSize, const size_t numberOfVertices,
const Renderer::Backend::IBuffer::Type type, 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(vertexSize > 0);
ENSURE(numberOfVertices > 0); ENSURE(numberOfVertices > 0);
CVertexBuffer::VBChunk* result = nullptr; CVertexBuffer::VBChunk* result = nullptr;
if (CVertexBuffer::UseStreaming(dynamic)) if (CVertexBuffer::UseStreaming(usage))
ENSURE(backingStore != NULL); ENSURE(backingStore != NULL);
// TODO, RC - run some sanity checks on allocation request // 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); debug_printf("\n============================\n# allocate vsize=%zu nverts=%zu\n\n", vertexSize, numVertices);
for (const std::unique_ptr<CVertexBuffer>& buffer : buffers) 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()); debug_printf("%p\n", buffer.get());
buffer->DumpStatus(); buffer->DumpStatus();
@ -142,7 +142,7 @@ CVertexBufferManager::Handle CVertexBufferManager::AllocateChunk(
// satisfy the allocation // satisfy the allocation
for (const std::unique_ptr<CVertexBuffer>& buffer : buffers) 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) if (result)
return Handle(result); return Handle(result);
} }
@ -150,15 +150,15 @@ CVertexBufferManager::Handle CVertexBufferManager::AllocateChunk(
char bufferName[64] = {0}; char bufferName[64] = {0};
snprintf( snprintf(
bufferName, std::size(bufferName), "%s (%s, %zu%s)", 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 // got this far; need to allocate a new buffer
buffers.emplace_back( buffers.emplace_back(
group == Group::DEFAULT 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. // Reduces the buffer size for not so frequent buffers.
: std::make_unique<CVertexBuffer>(m_Device, bufferName, vertexSize, type, dynamic, 1024 * 1024)); : std::make_unique<CVertexBuffer>(m_Device, bufferName, vertexSize, type, usage, 1024 * 1024));
result = buffers.back()->Allocate(vertexSize, numberOfVertices, type, dynamic, backingStore); result = buffers.back()->Allocate(vertexSize, numberOfVertices, type, usage, backingStore);
if (!result) 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -93,7 +93,7 @@ public:
Handle AllocateChunk( Handle AllocateChunk(
const size_t vertexSize, const size_t numberOfVertices, const size_t vertexSize, const size_t numberOfVertices,
const Renderer::Backend::IBuffer::Type type, 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 /// Returns the given @p chunk to its owning buffer
void Release(CVertexBuffer::VBChunk* chunk); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -649,7 +649,8 @@ void WaterManager::CreateWaveMeshes()
// Generic indexes, max-length // Generic indexes, max-length
m_ShoreWavesVBIndices = g_Renderer.GetVertexBufferManager().AllocateChunk( m_ShoreWavesVBIndices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(u16), water_indices.size(), 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); nullptr, CVertexBufferManager::Group::WATER);
m_ShoreWavesVBIndices->m_Owner->UpdateChunkVertices(m_ShoreWavesVBIndices.Get(), &water_indices[0]); 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( shoreWave->m_VBVertices = g_Renderer.GetVertexBufferManager().AllocateChunk(
sizeof(SWavesVertex), vertices.size(), 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); nullptr, CVertexBufferManager::Group::WATER);
shoreWave->m_VBVertices->m_Owner->UpdateChunkVertices(shoreWave->m_VBVertices.Get(), &vertices[0]); 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -39,9 +39,20 @@ public:
UNIFORM, 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 Type GetType() const = 0;
virtual uint32_t GetSize() 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 } // namespace Backend

View File

@ -122,7 +122,7 @@ public:
SDepthStencilAttachment* depthStencilAttachment) = 0; SDepthStencilAttachment* depthStencilAttachment) = 0;
virtual std::unique_ptr<IBuffer> CreateBuffer( 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( virtual std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) = 0; 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -32,13 +32,13 @@ namespace Dummy
// static // static
std::unique_ptr<IBuffer> CBuffer::Create( 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()); std::unique_ptr<CBuffer> buffer(new CBuffer());
buffer->m_Device = device; buffer->m_Device = device;
buffer->m_Type = type; buffer->m_Type = type;
buffer->m_Size = size; buffer->m_Size = size;
buffer->m_Dynamic = dynamic; buffer->m_Usage = usage;
return buffer; 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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; } Type GetType() const override { return m_Type; }
uint32_t GetSize() const override { return m_Size; } uint32_t GetSize() const override { return m_Size; }
bool IsDynamic() const override { return m_Dynamic; } uint32_t GetUsage() const override { return m_Usage; }
private: private:
friend class CDevice; friend class CDevice;
static std::unique_ptr<IBuffer> Create( 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(); CBuffer();
@ -56,7 +56,7 @@ private:
Type m_Type = Type::VERTEX; Type m_Type = Type::VERTEX;
uint32_t m_Size = 0; uint32_t m_Size = 0;
bool m_Dynamic = false; uint32_t m_Usage = 0;
}; };
} // namespace Dummy } // namespace Dummy

View File

@ -116,9 +116,9 @@ std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
} }
std::unique_ptr<IBuffer> CDevice::CreateBuffer( 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( std::unique_ptr<IShaderProgram> CDevice::CreateShaderProgram(

View File

@ -79,7 +79,7 @@ public:
SDepthStencilAttachment* depthStencilAttachment) override; SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer( 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( std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) override; 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -38,18 +38,18 @@ namespace GL
// static // static
std::unique_ptr<CBuffer> CBuffer::Create( std::unique_ptr<CBuffer> CBuffer::Create(
CDevice* device, const char* name, 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); ENSURE(type == Type::VERTEX || type == Type::INDEX);
std::unique_ptr<CBuffer> buffer(new CBuffer()); std::unique_ptr<CBuffer> buffer(new CBuffer());
buffer->m_Device = device; buffer->m_Device = device;
buffer->m_Type = type; buffer->m_Type = type;
buffer->m_Size = size; buffer->m_Size = size;
buffer->m_Dynamic = dynamic; buffer->m_Usage = usage;
glGenBuffersARB(1, &buffer->m_Handle); glGenBuffersARB(1, &buffer->m_Handle);
const GLenum target = type == Type::INDEX ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER; const GLenum target = type == Type::INDEX ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
glBindBufferARB(target, buffer->m_Handle); 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 !CONFIG2_GLES
if (buffer->m_Device->GetCapabilities().debugLabels) 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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; } Type GetType() const override { return m_Type; }
uint32_t GetSize() const override { return m_Size; } 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; } GLuint GetHandle() { return m_Handle; }
@ -53,14 +53,14 @@ private:
static std::unique_ptr<CBuffer> Create( static std::unique_ptr<CBuffer> Create(
CDevice* device, const char* name, 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(); CBuffer();
CDevice* m_Device = nullptr; CDevice* m_Device = nullptr;
Type m_Type = Type::VERTEX; Type m_Type = Type::VERTEX;
uint32_t m_Size = 0; uint32_t m_Size = 0;
bool m_Dynamic = false; uint32_t m_Usage = 0;
GLuint m_Handle = 0; GLuint m_Handle = 0;
}; };

View File

@ -904,9 +904,9 @@ std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
} }
std::unique_ptr<IBuffer> CDevice::CreateBuffer( 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( std::unique_ptr<IShaderProgram> CDevice::CreateShaderProgram(

View File

@ -94,7 +94,7 @@ public:
SDepthStencilAttachment* depthStencilAttachment) override; SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer( 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( std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) override; 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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/Device.h"
#include "renderer/backend/vulkan/Utilities.h" #include "renderer/backend/vulkan/Utilities.h"
#include <tuple>
namespace Renderer namespace Renderer
{ {
@ -31,47 +33,69 @@ namespace Backend
namespace Vulkan 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 // static
std::unique_ptr<CBuffer> CBuffer::Create( std::unique_ptr<CBuffer> CBuffer::Create(
CDevice* device, const char* name, const Type type, const uint32_t size, 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()); std::unique_ptr<CBuffer> buffer(new CBuffer());
buffer->m_Device = device; buffer->m_Device = device;
buffer->m_Type = type; buffer->m_Type = type;
buffer->m_Size = size; buffer->m_Size = size;
buffer->m_Dynamic = dynamic; buffer->m_Usage = usage;
VkMemoryPropertyFlags properties = 0; const auto [usageFlags, memoryProperties, memoryUsage] = MakeCreationFlags(type, usage);
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;
}
VkBufferCreateInfo bufferCreateInfo{}; VkBufferCreateInfo bufferCreateInfo{};
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferCreateInfo.size = size; bufferCreateInfo.size = size;
bufferCreateInfo.usage = usage; bufferCreateInfo.usage = usageFlags;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo allocationCreateInfo{}; VmaAllocationCreateInfo allocationCreateInfo{};
@ -81,7 +105,7 @@ std::unique_ptr<CBuffer> CBuffer::Create(
allocationCreateInfo.flags |= VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT; allocationCreateInfo.flags |= VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
allocationCreateInfo.pUserData = const_cast<char*>(name); allocationCreateInfo.pUserData = const_cast<char*>(name);
#endif #endif
allocationCreateInfo.requiredFlags = properties; allocationCreateInfo.requiredFlags = memoryProperties;
allocationCreateInfo.usage = memoryUsage; allocationCreateInfo.usage = memoryUsage;
const VkResult createBufferResult = vmaCreateBuffer( const VkResult createBufferResult = vmaCreateBuffer(
device->GetVMAAllocator(), &bufferCreateInfo, &allocationCreateInfo, 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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; } Type GetType() const override { return m_Type; }
uint32_t GetSize() const override { return m_Size; } 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; } VkBuffer GetVkBuffer() { return m_Buffer; }
@ -58,7 +58,7 @@ private:
static std::unique_ptr<CBuffer> Create( static std::unique_ptr<CBuffer> Create(
CDevice* device, const char* name, const Type type, const uint32_t size, CDevice* device, const char* name, const Type type, const uint32_t size,
const bool dynamic); const uint32_t usage);
CBuffer(); CBuffer();
@ -66,7 +66,7 @@ private:
Type m_Type = Type::VERTEX; Type m_Type = Type::VERTEX;
uint32_t m_Size = 0; uint32_t m_Size = 0;
bool m_Dynamic = false; uint32_t m_Usage = 0;
VkBuffer m_Buffer = VK_NULL_HANDLE; VkBuffer m_Buffer = VK_NULL_HANDLE;
VmaAllocation m_Allocation = 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( 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( 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( std::unique_ptr<IShaderProgram> CDevice::CreateShaderProgram(

View File

@ -101,10 +101,10 @@ public:
SDepthStencilAttachment* depthStencilAttachment) override; SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer( 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( 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( std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) override; 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_Capacity = std::max(m_Capacity * 2, round_up_to_pow2(dataSize));
m_Buffer = m_Device->CreateCBuffer( 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( 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); ENSURE(m_Buffer && m_StagingBuffer);
m_StagingBufferMappedData = static_cast<std::byte*>(m_StagingBuffer->GetMappedData()); m_StagingBufferMappedData = static_cast<std::byte*>(m_StagingBuffer->GetMappedData());
ENSURE(m_StagingBufferMappedData); 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), std::max(m_StagingBuffer ? m_StagingBuffer->GetSize() * 2 : INITIAL_STAGING_BUFFER_CAPACITY, minimumRequiredCapacity),
m_MaxStagingBufferCapacity); m_MaxStagingBufferCapacity);
m_StagingBuffer = m_Device->CreateCBuffer( m_StagingBuffer = m_Device->CreateCBuffer(
"UploadRingBuffer", IBuffer::Type::UPLOAD, newCapacity, false); "UploadRingBuffer", IBuffer::Type::UPLOAD, newCapacity, IBuffer::Usage::TRANSFER_SRC);
ENSURE(m_StagingBuffer); ENSURE(m_StagingBuffer);
m_StagingBufferFirst = 0; m_StagingBufferFirst = 0;
m_StagingBufferCurrentFirst = 0; m_StagingBufferCurrentFirst = 0;