Fix vulkan buffers not using the stream usage for the 2d drawer

Add BufferUsageType enum to clarify what kind of usage is expected by the buffer allocated by SetData
This commit is contained in:
Magnus Norddahl 2021-10-27 03:38:02 +02:00 committed by Rachael Alexanderson
parent efdc6a50a1
commit d853961a83
22 changed files with 96 additions and 66 deletions

View file

@ -306,8 +306,8 @@ public:
void UploadData(F2DDrawer::TwoDVertex *vertices, int vertcount, int *indices, int indexcount)
{
mVertexBuffer->SetData(vertcount * sizeof(*vertices), vertices, false);
mIndexBuffer->SetData(indexcount * sizeof(unsigned int), indices, false);
mVertexBuffer->SetData(vertcount * sizeof(*vertices), vertices, BufferUsageType::Stream);
mIndexBuffer->SetData(indexcount * sizeof(unsigned int), indices, BufferUsageType::Stream);
}
std::pair<IVertexBuffer *, IIndexBuffer *> GetBufferObjects() const

View file

@ -76,16 +76,20 @@ void GLBuffer::Bind()
}
void GLBuffer::SetData(size_t size, const void *data, bool staticdata)
void GLBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
{
Bind();
if (data != nullptr)
if (usage == BufferUsageType::Static)
{
glBufferData(mUseType, size, data, staticdata? GL_STATIC_DRAW : GL_STREAM_DRAW);
glBufferData(mUseType, size, data, GL_STATIC_DRAW);
}
else
else if (usage == BufferUsageType::Stream)
{
mPersistent = screen->BuffersArePersistent() && !staticdata;
glBufferData(mUseType, size, data, GL_STREAM_DRAW);
}
else if (usage == BufferUsageType::Persistent)
{
mPersistent = screen->BuffersArePersistent();
if (mPersistent)
{
glBufferStorage(mUseType, size, nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
@ -93,10 +97,15 @@ void GLBuffer::SetData(size_t size, const void *data, bool staticdata)
}
else
{
glBufferData(mUseType, size, nullptr, staticdata ? GL_STATIC_DRAW : GL_STREAM_DRAW);
glBufferData(mUseType, size, nullptr, GL_STREAM_DRAW);
map = nullptr;
}
if (!staticdata) nomap = false;
nomap = false;
}
else if (usage == BufferUsageType::Mappable)
{
glBufferData(mUseType, size, nullptr, GL_STATIC_DRAW);
map = nullptr;
}
buffersize = size;
InvalidateBufferState();
@ -134,7 +143,7 @@ void GLBuffer::Unmap()
void *GLBuffer::Lock(unsigned int size)
{
// This initializes this buffer as a static object with no data.
SetData(size, nullptr, true);
SetData(size, nullptr, BufferUsageType::Mappable);
return glMapBufferRange(mUseType, 0, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
}
@ -158,7 +167,7 @@ void GLBuffer::Resize(size_t newsize)
glUnmapBuffer(mUseType);
glGenBuffers(1, &mBufferId);
SetData(newsize, nullptr, false);
SetData(newsize, nullptr, BufferUsageType::Persistent);
glBindBuffer(GL_COPY_READ_BUFFER, oldbuffer);
// copy contents and delete the old buffer.

View file

@ -24,7 +24,7 @@ protected:
GLBuffer(int usetype);
~GLBuffer();
void SetData(size_t size, const void *data, bool staticdata) override;
void SetData(size_t size, const void *data, BufferUsageType usage) override;
void SetSubData(size_t offset, size_t size, const void *data) override;
void Map() override;
void Unmap() override;

View file

@ -952,7 +952,7 @@ void GLPPRenderState::Draw()
{
if (!shader->Uniforms)
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false, false));
shader->Uniforms->SetData(Uniforms.Data.Size(), Uniforms.Data.Data());
shader->Uniforms->SetData(Uniforms.Data.Size(), Uniforms.Data.Data(), BufferUsageType::Static);
static_cast<GLDataBuffer*>(shader->Uniforms.get())->BindBase();
}

View file

@ -93,8 +93,9 @@ void GLBuffer::Bind()
}
void GLBuffer::SetData(size_t size, const void* data, bool staticdata)
void GLBuffer::SetData(size_t size, const void* data, BufferUsageType usage)
{
bool staticdata = (usage == BufferUsageType::Static || usage == BufferUsageType::Mappable);
if (isData || !gles.useMappedBuffers)
{
if (memory)
@ -175,7 +176,7 @@ void GLBuffer::Unmap()
void *GLBuffer::Lock(unsigned int size)
{
// This initializes this buffer as a static object with no data.
SetData(size, nullptr, true);
SetData(size, nullptr, BufferUsageType::Mappable);
if (!isData && gles.useMappedBuffers)
{
return glMapBufferRange(mUseType, 0, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);

View file

@ -26,7 +26,7 @@ protected:
GLBuffer(int usetype);
~GLBuffer();
void SetData(size_t size, const void *data, bool staticdata) override;
void SetData(size_t size, const void *data, BufferUsageType usage) override;
void SetSubData(size_t offset, size_t size, const void *data) override;
void Map() override;
void Unmap() override;

View file

@ -88,7 +88,7 @@ public:
void SetData()
{
if (mBuffer != nullptr)
mBuffer->SetData(sizeof(T), &Values);
mBuffer->SetData(sizeof(T), &Values, BufferUsageType::Static);
}
IDataBuffer* GetBuffer() const

View file

@ -46,6 +46,14 @@ struct FVertexBufferAttribute
int offset;
};
enum class BufferUsageType
{
Static, // initial data is not null, staticdata is true
Stream, // initial data is not null, staticdata is false
Persistent, // initial data is null, staticdata is false
Mappable // initial data is null, staticdata is true
};
class IBuffer
{
protected:
@ -57,7 +65,7 @@ public:
IBuffer &operator=(const IBuffer &) = delete;
virtual ~IBuffer() = default;
virtual void SetData(size_t size, const void *data, bool staticdata = true) = 0;
virtual void SetData(size_t size, const void *data, BufferUsageType type) = 0;
virtual void SetSubData(size_t offset, size_t size, const void *data) = 0;
virtual void *Lock(unsigned int size) = 0;
virtual void Unlock() = 0;

View file

@ -81,7 +81,7 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr):
mIndexBuffer = screen->CreateIndexBuffer();
int data[4] = {};
mIndexBuffer->SetData(4, data); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes.
mIndexBuffer->SetData(4, data, BufferUsageType::Static); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes.
for (int n = 0; n < mPipelineNbr; n++)
@ -89,7 +89,7 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr):
mVertexBufferPipeline[n] = screen->CreateVertexBuffer();
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
mVertexBufferPipeline[n]->SetData(bytesize, nullptr, false);
mVertexBufferPipeline[n]->SetData(bytesize, nullptr, BufferUsageType::Persistent);
static const FVertexBufferAttribute format[] = {
{ 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) },

View file

@ -64,7 +64,7 @@ FLightBuffer::FLightBuffer(int pipelineNbr):
for (int n = 0; n < mPipelineNbr; n++)
{
mBufferPipeline[n] = screen->CreateDataBuffer(LIGHTBUF_BINDINGPOINT, mBufferType, false);
mBufferPipeline[n]->SetData(mByteSize, nullptr, false);
mBufferPipeline[n]->SetData(mByteSize, nullptr, BufferUsageType::Persistent);
}
Clear();

View file

@ -117,7 +117,7 @@ void IShadowMap::UploadLights()
if (mLightList == nullptr)
mLightList = screen->CreateDataBuffer(LIGHTLIST_BINDINGPOINT, true, false);
mLightList->SetData(sizeof(float) * mLights.Size(), &mLights[0]);
mLightList->SetData(sizeof(float) * mLights.Size(), &mLights[0], BufferUsageType::Stream);
}
@ -129,11 +129,11 @@ void IShadowMap::UploadAABBTree()
if (!mNodesBuffer)
mNodesBuffer = screen->CreateDataBuffer(LIGHTNODES_BINDINGPOINT, true, false);
mNodesBuffer->SetData(mAABBTree->NodesSize(), mAABBTree->Nodes());
mNodesBuffer->SetData(mAABBTree->NodesSize(), mAABBTree->Nodes(), BufferUsageType::Static);
if (!mLinesBuffer)
mLinesBuffer = screen->CreateDataBuffer(LIGHTLINES_BINDINGPOINT, true, false);
mLinesBuffer->SetData(mAABBTree->LinesSize(), mAABBTree->Lines());
mLinesBuffer->SetData(mAABBTree->LinesSize(), mAABBTree->Lines(), BufferUsageType::Static);
}
else if (mAABBTree->Update())
{

View file

@ -130,7 +130,7 @@ FSkyVertexBuffer::FSkyVertexBuffer()
{ 0, VATTR_COLOR, VFmt_Byte4, (int)myoffsetof(FSkyVertex, color) }
};
mVertexBuffer->SetFormat(1, 3, sizeof(FSkyVertex), format);
mVertexBuffer->SetData(mVertices.Size() * sizeof(FSkyVertex), &mVertices[0], true);
mVertexBuffer->SetData(mVertices.Size() * sizeof(FSkyVertex), &mVertices[0], BufferUsageType::Static);
}
FSkyVertexBuffer::~FSkyVertexBuffer()

View file

@ -43,7 +43,7 @@ HWViewpointBuffer::HWViewpointBuffer(int pipelineNbr):
for (int n = 0; n < mPipelineNbr; n++)
{
mBufferPipeline[n] = screen->CreateDataBuffer(VIEWPOINT_BINDINGPOINT, false, true);
mBufferPipeline[n]->SetData(mByteSize, nullptr, false);
mBufferPipeline[n]->SetData(mByteSize, nullptr, BufferUsageType::Persistent);
}
Clear();

View file

@ -129,7 +129,7 @@ public:
void SetData()
{
if (mBuffer != nullptr)
mBuffer->SetData(sizeof(T), &Values);
mBuffer->SetData(sizeof(T), &Values, BufferUsageType::Static);
}
IDataBuffer* GetBuffer() const

View file

@ -56,7 +56,7 @@ void PolyBuffer::Reset()
{
}
void PolyBuffer::SetData(size_t size, const void *data, bool staticdata)
void PolyBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
{
mData.resize(size);
map = mData.data();

View file

@ -20,7 +20,7 @@ public:
static void ResetAll();
void Reset();
void SetData(size_t size, const void *data, bool staticdata) override;
void SetData(size_t size, const void *data, BufferUsageType usage) override;
void SetSubData(size_t offset, size_t size, const void *data) override;
void Resize(size_t newsize) override;

View file

@ -111,7 +111,7 @@ void PolyFrameBuffer::InitializeState()
mScreenQuad.VertexBuffer->SetFormat(1, 3, sizeof(ScreenQuadVertex), format);
mScreenQuad.IndexBuffer = screen->CreateIndexBuffer();
mScreenQuad.IndexBuffer->SetData(6 * sizeof(uint32_t), indices, false);
mScreenQuad.IndexBuffer->SetData(6 * sizeof(uint32_t), indices, BufferUsageType::Stream);
CheckCanvas();
}
@ -254,7 +254,7 @@ void PolyFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash, c
{ 0.0f, (float)mScreenViewport.height, 0.0f, 1.0f },
{ (float)mScreenViewport.width, (float)mScreenViewport.height, 1.0f, 1.0f }
};
mScreenQuad.VertexBuffer->SetData(4 * sizeof(ScreenQuadVertex), vertices, false);
mScreenQuad.VertexBuffer->SetData(4 * sizeof(ScreenQuadVertex), vertices, BufferUsageType::Stream);
mRenderState->SetVertexBuffer(mScreenQuad.VertexBuffer, 0, 0);
mRenderState->SetIndexBuffer(mScreenQuad.IndexBuffer);

View file

@ -30,7 +30,7 @@ VkStreamBuffer::VkStreamBuffer(size_t structSize, size_t count)
mBlockSize = static_cast<uint32_t>((structSize + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment);
UniformBuffer = (VKDataBuffer*)GetVulkanFrameBuffer()->CreateDataBuffer(-1, false, false);
UniformBuffer->SetData(mBlockSize * count, nullptr, false);
UniformBuffer->SetData(mBlockSize * count, nullptr, BufferUsageType::Persistent);
}
VkStreamBuffer::~VkStreamBuffer()

View file

@ -64,61 +64,73 @@ void VKBuffer::Reset()
mStaging.reset();
}
void VKBuffer::SetData(size_t size, const void *data, bool staticdata)
void VKBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
{
auto fb = GetVulkanFrameBuffer();
size = std::max(size, (size_t)16); // For supporting zero byte buffers
size_t bufsize = std::max(size, (size_t)16); // For supporting zero byte buffers
if (staticdata)
if (usage == BufferUsageType::Static || usage == BufferUsageType::Stream)
{
// Note: we could recycle buffers here for the stream usage type to improve performance
mPersistent = false;
{
BufferBuilder builder;
builder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | mBufferType, VMA_MEMORY_USAGE_GPU_ONLY);
builder.setSize(size);
mBuffer = builder.create(fb->device);
}
BufferBuilder builder;
builder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | mBufferType, VMA_MEMORY_USAGE_GPU_ONLY);
builder.setSize(bufsize);
mBuffer = builder.create(fb->device);
{
BufferBuilder builder;
builder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
builder.setSize(size);
mStaging = builder.create(fb->device);
}
BufferBuilder builder2;
builder2.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
builder2.setSize(bufsize);
mStaging = builder2.create(fb->device);
void *dst = mStaging->Map(0, size);
memcpy(dst, data, size);
mStaging->Unmap();
if (data)
{
void* dst = mStaging->Map(0, bufsize);
memcpy(dst, data, size);
mStaging->Unmap();
}
fb->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get());
}
else
else if (usage == BufferUsageType::Persistent)
{
mPersistent = screen->BuffersArePersistent();
mPersistent = true;
BufferBuilder builder;
builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, mPersistent ? VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT : 0);
builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT);
builder.setMemoryType(
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
builder.setSize(size);
builder.setSize(bufsize);
mBuffer = builder.create(fb->device);
if (mPersistent)
map = mBuffer->Map(0, bufsize);
if (data)
memcpy(map, data, size);
}
else if (usage == BufferUsageType::Mappable)
{
mPersistent = false;
BufferBuilder builder;
builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, 0);
builder.setMemoryType(
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
builder.setSize(bufsize);
mBuffer = builder.create(fb->device);
if (data)
{
map = mBuffer->Map(0, size);
if (data)
memcpy(map, data, size);
}
else if (data)
{
void *dst = mBuffer->Map(0, size);
void* dst = mBuffer->Map(0, bufsize);
memcpy(dst, data, size);
mBuffer->Unmap();
}
}
buffersize = size;
}
@ -214,7 +226,7 @@ void VKBuffer::Unlock()
if (!mBuffer)
{
map = nullptr;
SetData(mStaticUpload.Size(), mStaticUpload.Data(), true);
SetData(mStaticUpload.Size(), mStaticUpload.Data(), BufferUsageType::Static);
mStaticUpload.Clear();
}
else if (!mPersistent)

View file

@ -19,7 +19,7 @@ public:
static void ResetAll();
void Reset();
void SetData(size_t size, const void *data, bool staticdata) override;
void SetData(size_t size, const void *data, BufferUsageType usage) override;
void SetSubData(size_t offset, size_t size, const void *data) override;
void Resize(size_t newsize) override;

View file

@ -721,7 +721,7 @@ void VulkanFrameBuffer::CreateFanToTrisIndexBuffer()
}
FanToTrisIndexBuffer.reset(CreateIndexBuffer());
FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data());
FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data(), BufferUsageType::Static);
}
void VulkanFrameBuffer::UpdateShadowMap()

View file

@ -400,5 +400,5 @@ void CreateVBO(FFlatVertexBuffer* fvb, TArray<sector_t>& sectors)
CreateVertices(fvb, sectors);
fvb->mCurIndex = fvb->mIndex = fvb->vbo_shadowdata.Size();
fvb->Copy(0, fvb->mIndex);
fvb->mIndexBuffer->SetData(fvb->ibo_data.Size() * sizeof(uint32_t), &fvb->ibo_data[0]);
fvb->mIndexBuffer->SetData(fvb->ibo_data.Size() * sizeof(uint32_t), &fvb->ibo_data[0], BufferUsageType::Static);
}