Move bone buffer to backend

This commit is contained in:
Magnus Norddahl 2023-04-30 04:49:06 +02:00 committed by Christoph Oelckers
parent d24ffc021b
commit 930107636e
16 changed files with 42 additions and 191 deletions

View file

@ -1101,7 +1101,6 @@ set (PCH_SOURCES
common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp
common/rendering/hwrenderer/data/hw_cvars.cpp
common/rendering/hwrenderer/data/hw_vrmodes.cpp
common/rendering/hwrenderer/data/hw_bonebuffer.cpp
common/rendering/hwrenderer/data/hw_aabbtree.cpp
common/rendering/hwrenderer/data/hw_shadowmap.cpp
common/rendering/hwrenderer/data/hw_shaderpatcher.cpp

View file

@ -1,109 +0,0 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2014-2016 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
#include "hw_bonebuffer.h"
#include "hw_dynlightdata.h"
#include "v_video.h"
static const int BONE_SIZE = (16*sizeof(float));
BoneBuffer::BoneBuffer(DFrameBuffer* fb, int pipelineNbr) : fb(fb), mPipelineNbr(pipelineNbr)
{
int maxNumberOfBones = 80000;
mBufferSize = maxNumberOfBones;
mByteSize = mBufferSize * BONE_SIZE;
//if (fb->useSSBO())
{
mBufferType = true;
mBlockAlign = 0;
mBlockSize = mBufferSize;
mMaxUploadSize = mBlockSize;
}
/*else
{
mBufferType = false;
mBlockSize = fb->maxuniformblock / BONE_SIZE;
mBlockAlign = fb->uniformblockalignment < 64 ? 1 : fb->uniformblockalignment / BONE_SIZE;
mMaxUploadSize = (mBlockSize - mBlockAlign);
}*/
for (int n = 0; n < mPipelineNbr; n++)
{
mBufferPipeline[n] = fb->CreateBoneBuffer();
mBufferPipeline[n]->SetData(mByteSize, nullptr, BufferUsageType::Persistent);
}
Clear();
}
BoneBuffer::~BoneBuffer()
{
delete mBuffer;
}
void BoneBuffer::Clear()
{
mIndex = 0;
mPipelinePos++;
mPipelinePos %= mPipelineNbr;
mBuffer = mBufferPipeline[mPipelinePos];
}
int BoneBuffer::UploadBones(const TArray<VSMatrix>& bones)
{
int totalsize = bones.Size();
if (totalsize > (int)mMaxUploadSize)
{
totalsize = mMaxUploadSize;
}
uint8_t *mBufferPointer = (uint8_t*)mBuffer->Memory();
assert(mBufferPointer != nullptr);
if (mBufferPointer == nullptr) return -1;
if (totalsize <= 0) return -1; // there are no bones
unsigned int thisindex = mIndex.fetch_add(totalsize);
if (thisindex + totalsize <= mBufferSize)
{
memcpy(mBufferPointer + thisindex * BONE_SIZE, bones.Data(), totalsize * BONE_SIZE);
return thisindex;
}
else
{
return -1; // Buffer is full. Since it is being used live at the point of the upload we cannot do much here but to abort.
}
}
int BoneBuffer::GetBinding(unsigned int index, size_t* pOffset, size_t* pSize)
{
// this function will only get called if a uniform buffer is used. For a shader storage buffer we only need to bind the buffer once at the start.
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
*pOffset = offset * BONE_SIZE;
*pSize = mBlockSize * BONE_SIZE;
return (index - offset);
}

View file

@ -1,48 +0,0 @@
#pragma once
#include "tarray.h"
#include "hwrenderer/data/buffers.h"
#include "common/utility/matrix.h"
#include <atomic>
#include <mutex>
class DFrameBuffer;
class FRenderState;
class BoneBuffer
{
DFrameBuffer* fb = nullptr;
IBuffer *mBuffer;
IBuffer* mBufferPipeline[HW_MAX_PIPELINE_BUFFERS];
int mPipelineNbr;
int mPipelinePos = 0;
bool mBufferType;
std::atomic<unsigned int> mIndex;
unsigned int mBlockAlign;
unsigned int mBlockSize;
unsigned int mBufferSize;
unsigned int mByteSize;
unsigned int mMaxUploadSize;
public:
BoneBuffer(DFrameBuffer* fb, int pipelineNbr = 1);
~BoneBuffer();
void Clear();
int UploadBones(const TArray<VSMatrix> &bones);
void Map() { mBuffer->Map(); }
void Unmap() { mBuffer->Unmap(); }
unsigned int GetBlockSize() const { return mBlockSize; }
bool GetBufferType() const { return mBufferType; }
int GetBinding(unsigned int index, size_t* pOffset, size_t* pSize);
// Only for GLES to determin how much data is in the buffer
int GetCurrentIndex() { return mIndex; };
// OpenGL needs the buffer to mess around with the binding.
IBuffer* GetBuffer() const
{
return mBuffer;
}
};

View file

@ -69,6 +69,7 @@ public:
int SetViewpoint(const HWViewpointUniforms& vp) override { return 0; }
void SetViewpoint(int index) override { }
int UploadLights(const FDynLightData& lightdata) override { return -1; }
int UploadBones(const TArray<VSMatrix>& bones) override { return -1; }
// Draw commands
void Draw(int dt, int index, int count, bool apply = true) override;

View file

@ -760,6 +760,7 @@ public:
virtual int SetViewpoint(const HWViewpointUniforms& vp) = 0;
virtual void SetViewpoint(int index) = 0;
virtual int UploadLights(const FDynLightData& lightdata) = 0;
virtual int UploadBones(const TArray<VSMatrix>& bones) = 0;
// Draw commands
virtual void ClearScreen() = 0;

View file

@ -56,7 +56,6 @@ struct HWDrawInfo;
class FMaterial;
class FGameTexture;
class FRenderState;
class BoneBuffer;
enum EHWCaps
{
@ -139,7 +138,6 @@ public:
const char *vendorstring; // We have to account for some issues with particular vendors.
FSkyVertexBuffer *mSkyData = nullptr; // the sky vertex buffer
FFlatVertexBuffer *mVertexData = nullptr; // Global vertex data
BoneBuffer* mBones = nullptr; // Model bones
ShadowMap* mShadowMap = nullptr;
int mGameScreenWidth = 0;
@ -236,7 +234,6 @@ public:
bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); }
// To do: these buffers shouldn't be created by the hwrenderer layer - it will be simpler if the backend manages them completely
virtual IBuffer* CreateBoneBuffer() { return nullptr; }
virtual IBuffer* CreateShadowmapNodesBuffer() { return nullptr; }
virtual IBuffer* CreateShadowmapLinesBuffer() { return nullptr; }
virtual IBuffer* CreateShadowmapLightsBuffer() { return nullptr; }

View file

@ -46,6 +46,9 @@ void VkBufferManager::Init()
Lightbuffer.SSO.reset(new VkHardwareDataBuffer(fb, true, false));
Lightbuffer.SSO->SetData(Lightbuffer.Count * 4 * sizeof(FVector4), nullptr, BufferUsageType::Persistent);
Bonebuffer.SSO.reset(new VkHardwareDataBuffer(fb, true, false));
Bonebuffer.SSO->SetData(Bonebuffer.Count * sizeof(VSMatrix), nullptr, BufferUsageType::Persistent);
CreateFanToTrisIndexBuffer();
}
@ -53,6 +56,7 @@ void VkBufferManager::Deinit()
{
Viewpoint.UBO.reset();
Lightbuffer.SSO.reset();
Bonebuffer.SSO.reset();
while (!Buffers.empty())
RemoveBuffer(Buffers.back());
@ -69,7 +73,7 @@ void VkBufferManager::RemoveBuffer(VkHardwareBuffer* buffer)
buffer->fb = nullptr;
Buffers.erase(buffer->it);
for (VkHardwareDataBuffer** knownbuf : { &LightNodes, &LightLines, &LightList, &BoneBufferSSO})
for (VkHardwareDataBuffer** knownbuf : { &LightNodes, &LightLines, &LightList})
{
if (buffer == *knownbuf) *knownbuf = nullptr;
}
@ -85,12 +89,6 @@ IBuffer* VkBufferManager::CreateIndexBuffer()
return new VkHardwareIndexBuffer(fb);
}
IBuffer* VkBufferManager::CreateBoneBuffer()
{
BoneBufferSSO = new VkHardwareDataBuffer(fb, true, false);
return BoneBufferSSO;
}
IBuffer* VkBufferManager::CreateShadowmapNodesBuffer()
{
LightNodes = new VkHardwareDataBuffer(fb, true, false);

View file

@ -24,7 +24,6 @@ public:
IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs);
IBuffer* CreateIndexBuffer();
IBuffer* CreateBoneBuffer();
IBuffer* CreateShadowmapNodesBuffer();
IBuffer* CreateShadowmapLinesBuffer();
IBuffer* CreateShadowmapLightsBuffer();
@ -47,10 +46,16 @@ public:
std::unique_ptr<VkHardwareDataBuffer> SSO;
} Lightbuffer;
struct
{
int UploadIndex = 0;
int Count = 80000;
std::unique_ptr<VkHardwareDataBuffer> SSO;
} Bonebuffer;
VkHardwareDataBuffer* LightNodes = nullptr;
VkHardwareDataBuffer* LightLines = nullptr;
VkHardwareDataBuffer* LightList = nullptr;
VkHardwareDataBuffer* BoneBufferSSO = nullptr;
std::unique_ptr<VkStreamBuffer> MatrixBuffer;
std::unique_ptr<VkStreamBuffer> StreamBuffer;

View file

@ -85,7 +85,7 @@ void VkDescriptorSetManager::UpdateHWBufferSet()
.AddBuffer(HWBufferSet.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO))
.AddBuffer(HWBufferSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO))
.AddBuffer(HWBufferSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->Lightbuffer.SSO->mBuffer.get())
.AddBuffer(HWBufferSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->BoneBufferSSO->mBuffer.get())
.AddBuffer(HWBufferSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->Bonebuffer.SSO->mBuffer.get())
.Execute(fb->GetDevice());
}

View file

@ -38,7 +38,6 @@
#include "hw_cvars.h"
#include "hw_skydome.h"
#include "flatvertices.h"
#include "hw_bonebuffer.h"
#include "vk_renderdevice.h"
#include "vulkan/vk_renderstate.h"
@ -132,7 +131,6 @@ VulkanRenderDevice::~VulkanRenderDevice()
delete mVertexData;
delete mSkyData;
delete mBones;
delete mShadowMap;
if (mDescriptorSetManager)
@ -189,7 +187,6 @@ void VulkanRenderDevice::InitializeState()
mVertexData = new FFlatVertexBuffer(this, GetWidth(), GetHeight());
mSkyData = new FSkyVertexBuffer(this);
mBones = new BoneBuffer(this);
mShadowMap = new ShadowMap(this);
mShaderManager.reset(new VkShaderManager(this));
@ -316,11 +313,6 @@ IBuffer*VulkanRenderDevice::CreateIndexBuffer()
return GetBufferManager()->CreateIndexBuffer();
}
IBuffer* VulkanRenderDevice::CreateBoneBuffer()
{
return GetBufferManager()->CreateBoneBuffer();
}
IBuffer* VulkanRenderDevice::CreateShadowmapNodesBuffer()
{
return GetBufferManager()->CreateShadowmapNodesBuffer();

View file

@ -74,7 +74,6 @@ public:
IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs) override;
IBuffer* CreateIndexBuffer() override;
IBuffer* CreateBoneBuffer() override;
IBuffer* CreateShadowmapNodesBuffer() override;
IBuffer* CreateShadowmapLinesBuffer() override;
IBuffer* CreateShadowmapLightsBuffer() override;

View file

@ -554,12 +554,37 @@ int VkRenderState::UploadLights(const FDynLightData& data)
}
}
int VkRenderState::UploadBones(const TArray<VSMatrix>& bones)
{
auto buffers = fb->GetBufferManager();
int totalsize = bones.Size();
if (bones.Size() == 0)
{
return -1;
}
int thisindex = buffers->Bonebuffer.UploadIndex;
buffers->Bonebuffer.UploadIndex += totalsize;
if (thisindex + totalsize <= buffers->Bonebuffer.Count)
{
memcpy((VSMatrix*)buffers->Bonebuffer.SSO->Memory() + thisindex, bones.Data(), bones.Size() * sizeof(VSMatrix));
return thisindex;
}
else
{
return -1; // Buffer is full. Since it is being used live at the point of the upload we cannot do much here but to abort.
}
}
void VkRenderState::BeginFrame()
{
mMaterial.Reset();
mApplyCount = 0;
fb->GetBufferManager()->Viewpoint.UploadIndex = 0;
fb->GetBufferManager()->Lightbuffer.UploadIndex = 0;
fb->GetBufferManager()->Bonebuffer.UploadIndex = 0;
}
void VkRenderState::EndRenderPass()

View file

@ -51,6 +51,7 @@ public:
int SetViewpoint(const HWViewpointUniforms& vp) override;
void SetViewpoint(int index) override;
int UploadLights(const FDynLightData& lightdata) override;
int UploadBones(const TArray<VSMatrix>& bones) override;
protected:
void Apply(int dt);

View file

@ -43,7 +43,6 @@
#include "g_cvars.h"
#include "v_draw.h"
#include "hw_bonebuffer.h"
#include "hw_cvars.h"
#include "hwrenderer/scene/hw_fakeflat.h"
#include "hwrenderer/scene/hw_clipper.h"
@ -278,7 +277,6 @@ void WriteSavePic(player_t* player, FileWriter* file, int width, int height)
hw_ClearFakeFlat();
screen->mVertexData->Reset();
RenderState.SetVertexBuffer(screen->mVertexData);
screen->mBones->Clear();
// This shouldn't overwrite the global viewpoint even for a short time.
FRenderViewpoint savevp;
@ -342,8 +340,6 @@ sector_t* RenderView(player_t* player)
if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.;
else r_viewpoint.TicFrac = I_GetTimeFrac();
screen->mBones->Clear();
// NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below.
bool saved_niv = NoInterpolateView;
NoInterpolateView = false;

View file

@ -41,7 +41,6 @@
#include "hwrenderer/scene/hw_drawinfo.h"
#include "hw_renderstate.h"
#include "hwrenderer/scene/hw_portal.h"
#include "hw_bonebuffer.h"
#include "hw_models.h"
CVAR(Bool, gl_light_models, true, CVAR_ARCHIVE)
@ -157,9 +156,7 @@ void FHWModelRenderer::DrawElements(int numIndices, size_t offset)
int FHWModelRenderer::SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray<VSMatrix>& bones, int boneStartIndex)
{
auto mdbuff = static_cast<FModelVertexBuffer*>(model->GetVertexBuffer(GetType()));
screen->mBones->Map();
boneIndexBase = boneStartIndex >= 0 ? boneStartIndex : screen->mBones->UploadBones(bones);
screen->mBones->Unmap();
boneIndexBase = boneStartIndex >= 0 ? boneStartIndex : state.UploadBones(bones);
state.SetBoneIndexBase(boneIndexBase);
if (mdbuff)
{

View file

@ -39,7 +39,6 @@
#include "hw_clock.h"
#include "hw_cvars.h"
#include "flatvertices.h"
#include "hw_bonebuffer.h"
#include "hw_vrmodes.h"
#include "hw_clipper.h"
#include "hw_meshcache.h"
@ -449,7 +448,6 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state)
// clip the scene and fill the drawlists
screen->mVertexData->Map();
screen->mBones->Map();
if (!gl_meshcache)
RenderBSP(Level->HeadNode(), drawpsprites, state);
@ -462,7 +460,6 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state)
HandleHackedSubsectors(state); // open sector hacks for deep water
PrepareUnhandledMissingTextures(state);
DispatchRenderHacks(state);
screen->mBones->Unmap();
screen->mVertexData->Unmap();
ProcessAll.Unclock();