diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a21134eee..397e4273f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1106,7 +1106,6 @@ set (PCH_SOURCES common/rendering/hwrenderer/hw_draw2d.cpp common/rendering/hwrenderer/data/hw_clock.cpp common/rendering/hwrenderer/data/hw_skydome.cpp - common/rendering/hwrenderer/data/flatvertices.cpp common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp common/rendering/hwrenderer/data/hw_cvars.cpp common/rendering/hwrenderer/data/hw_vrmodes.cpp diff --git a/src/common/rendering/hwrenderer/data/flatvertices.cpp b/src/common/rendering/hwrenderer/data/flatvertices.cpp deleted file mode 100644 index 3005db288..000000000 --- a/src/common/rendering/hwrenderer/data/flatvertices.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* -** hw_flatvertices.cpp -** Creates flat vertex data for hardware rendering. -** -**--------------------------------------------------------------------------- -** Copyright 2010-2020 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include "c_cvars.h" -#include "flatvertices.h" -#include "v_video.h" -#include "cmdlib.h" -#include "printf.h" -#include "hwrenderer/data/buffers.h" -#include "hw_renderstate.h" - -//========================================================================== -// -// -// -//========================================================================== - -FFlatVertexBuffer::FFlatVertexBuffer(DFrameBuffer* fb, int width, int height, int pipelineNbr) : fb(fb), mPipelineNbr(pipelineNbr) -{ - mIndexBuffer = fb->CreateIndexBuffer(); - int data[4] = {}; - 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++) - { - static const FVertexBufferAttribute format[] = - { - { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) }, - { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }, - { 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FFlatVertex, lu) }, - }; - - mVertexBufferPipeline[n] = fb->CreateVertexBuffer(1, 3, sizeof(FFlatVertex), format); - mVertexBufferPipeline[n]->SetData(BUFFER_SIZE * sizeof(FFlatVertex), nullptr, BufferUsageType::Persistent); - } - - mVertexBuffer = mVertexBufferPipeline[mPipelinePos]; - - mIndex = mCurIndex = 0; -} - -//========================================================================== -// -// -// -//========================================================================== - -FFlatVertexBuffer::~FFlatVertexBuffer() -{ - for (int n = 0; n < mPipelineNbr; n++) - { - delete mVertexBufferPipeline[n]; - } - - delete mIndexBuffer; - mIndexBuffer = nullptr; - mVertexBuffer = nullptr; -} - -//========================================================================== -// -// -// -//========================================================================== - -std::pair FFlatVertexBuffer::AllocVertices(unsigned int count) -{ - FFlatVertex *p = GetBuffer(); - auto index = mCurIndex.fetch_add(count); - if (index + count >= BUFFER_SIZE_TO_USE) - { - // If a single scene needs 2'000'000 vertices there must be something very wrong. - I_FatalError("Out of vertex memory. Tried to allocate more than %u vertices for a single frame", index + count); - } - return std::make_pair(p, index); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FFlatVertexBuffer::Copy(int start, int count) -{ - IBuffer* old = mVertexBuffer; - - for (int n = 0; n < mPipelineNbr; n++) - { - mVertexBuffer = mVertexBufferPipeline[n]; - Map(); - memcpy(GetBuffer(start), vbo_shadowdata.Data(), count * sizeof(FFlatVertex)); - Unmap(); - mVertexBuffer->Upload(start * sizeof(FFlatVertex), count * sizeof(FFlatVertex)); - } - - mVertexBuffer = old; -} diff --git a/src/common/rendering/hwrenderer/data/flatvertices.h b/src/common/rendering/hwrenderer/data/flatvertices.h index fd3c772cb..eac2107e7 100644 --- a/src/common/rendering/hwrenderer/data/flatvertices.h +++ b/src/common/rendering/hwrenderer/data/flatvertices.h @@ -1,15 +1,4 @@ - -#ifndef _HW__VERTEXBUFFER_H -#define _HW__VERTEXBUFFER_H - -#include "tarray.h" -#include "hwrenderer/data/buffers.h" -#include -#include - -class DFrameBuffer; -class FRenderState; -struct secplane_t; +#pragma once struct FFlatVertex { @@ -54,84 +43,3 @@ struct FFlatVertex } }; - -class FFlatVertexBuffer -{ - DFrameBuffer* fb = nullptr; -public: - TArray vbo_shadowdata; - TArray ibo_data; - - int mPipelineNbr; - int mPipelinePos = 0; - - IBuffer* mVertexBuffer; - IBuffer* mVertexBufferPipeline[HW_MAX_PIPELINE_BUFFERS]; - IBuffer* mIndexBuffer; - - - - unsigned int mIndex; - std::atomic mCurIndex; - - unsigned int mMapStart; - - static const unsigned int BUFFER_SIZE = 2000000; - static const unsigned int BUFFER_SIZE_TO_USE = BUFFER_SIZE-500; - -public: - FFlatVertexBuffer(DFrameBuffer* fb, int width, int height, int pipelineNbr = 1); - ~FFlatVertexBuffer(); - - std::pair GetBufferObjects() const - { - return std::make_pair(mVertexBuffer, mIndexBuffer); - } - - void Copy(int start, int count); - - FFlatVertex *GetBuffer(int index) const - { - FFlatVertex *ff = (FFlatVertex*)mVertexBuffer->Memory(); - return &ff[index]; - } - - FFlatVertex *GetBuffer() const - { - return GetBuffer(mCurIndex); - } - - std::pair AllocVertices(unsigned int count); - - void Reset() - { - mCurIndex = mIndex; - } - - void NextPipelineBuffer() - { - mPipelinePos++; - mPipelinePos %= mPipelineNbr; - - mVertexBuffer = mVertexBufferPipeline[mPipelinePos]; - } - - void Map() - { - mMapStart = mCurIndex; - mVertexBuffer->Map(); - } - - void Unmap() - { - mVertexBuffer->Unmap(); - mVertexBuffer->Upload(mMapStart * sizeof(FFlatVertex), (mCurIndex - mMapStart) * sizeof(FFlatVertex)); - } - - int GetPipelinePos() - { - return mPipelinePos; - } -}; - -#endif diff --git a/src/common/rendering/hwrenderer/data/hw_mesh.cpp b/src/common/rendering/hwrenderer/data/hw_mesh.cpp index 1dc663564..427620037 100644 --- a/src/common/rendering/hwrenderer/data/hw_mesh.cpp +++ b/src/common/rendering/hwrenderer/data/hw_mesh.cpp @@ -71,7 +71,7 @@ void Mesh::Draw(FRenderState& renderstate) #ifdef USE_MESH_VERTEX_BUFFER if (mVertexBuffer) - renderstate.SetVertexBuffer(screen->mVertexData); + renderstate.SetFlatVertexBuffer(); #endif for (const MeshDrawCommand& cmd : mIndexedDraws) diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp index 586ef1b48..988f087a5 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp @@ -17,9 +17,6 @@ MeshBuilder::MeshBuilder() ClearDepthBias(); EnableTexture(1); EnableBrightmap(true); - - // Add the vbo_shadowdata as some geometry might use it - mVertices = screen->mVertexData->vbo_shadowdata; } void MeshBuilder::SetShadowData(const TArray& vertices, const TArray& indexes) diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h index 09382c9bc..c111caf3e 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h @@ -70,7 +70,8 @@ public: // Vertices std::pair AllocVertices(unsigned int count) override; void SetShadowData(const TArray& vertices, const TArray& indexes) override; - void UpdateShadowData(unsigned int index, const FFlatVertex* vertices, unsigned int count) { } + void UpdateShadowData(unsigned int index, const FFlatVertex* vertices, unsigned int count) override { } + void ResetVertices() override { } // Buffers int SetViewpoint(const HWViewpointUniforms& vp) override { return 0; } diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index ee83ef715..8c753f044 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -659,9 +659,8 @@ public: mStreamData.uClipSplit.Y = 1000000.f; } - void SetVertexBuffer(IBuffer* vb, int offset0, int offset1) + void SetVertexBuffer(IBuffer* vb, int offset0 = 0, int offset1 = 0) { - assert(vb); mVertexBuffer = vb; mVertexOffsets[0] = offset0; mVertexOffsets[1] = offset1; @@ -672,11 +671,10 @@ public: mIndexBuffer = ib; } - template void SetVertexBuffer(T *buffer) + void SetFlatVertexBuffer() { - auto ptrs = buffer->GetBufferObjects(); - SetVertexBuffer(ptrs.first, 0, 0); - SetIndexBuffer(ptrs.second); + SetVertexBuffer(nullptr); + SetIndexBuffer(nullptr); } void SetInterpolationFactor(float fac) @@ -737,6 +735,7 @@ public: virtual std::pair AllocVertices(unsigned int count) = 0; virtual void SetShadowData(const TArray& vertices, const TArray& indexes) = 0; virtual void UpdateShadowData(unsigned int index, const FFlatVertex* vertices, unsigned int count) = 0; + virtual void ResetVertices() = 0; // Buffers virtual int SetViewpoint(const HWViewpointUniforms& vp) = 0; diff --git a/src/common/rendering/hwrenderer/data/hw_skydome.h b/src/common/rendering/hwrenderer/data/hw_skydome.h index 5103c8af8..7bd402289 100644 --- a/src/common/rendering/hwrenderer/data/hw_skydome.h +++ b/src/common/rendering/hwrenderer/data/hw_skydome.h @@ -86,10 +86,6 @@ public: FSkyVertexBuffer(DFrameBuffer* fb); ~FSkyVertexBuffer(); void SetupMatrices(FRenderState& state, FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale = 0, float vertscale = 0); - std::pair GetBufferObjects() const - { - return std::make_pair(mVertexBuffer, nullptr); - } int FaceStart(int i) { diff --git a/src/common/rendering/hwrenderer/hw_draw2d.cpp b/src/common/rendering/hwrenderer/hw_draw2d.cpp index b544fa774..6300d6d02 100644 --- a/src/common/rendering/hwrenderer/hw_draw2d.cpp +++ b/src/common/rendering/hwrenderer/hw_draw2d.cpp @@ -89,7 +89,8 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int } F2DVertexBuffer vb; vb.UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size()); - state.SetVertexBuffer(&vb); + state.SetVertexBuffer(vb.GetBufferObjects().first); + state.SetIndexBuffer(vb.GetBufferObjects().second); state.EnableFog(false); for(auto &cmd : commands) @@ -207,9 +208,12 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int if (cmd.shape2DBufInfo != nullptr) { - state.SetVertexBuffer(&cmd.shape2DBufInfo->buffers[cmd.shape2DBufIndex]); + auto& buffers = cmd.shape2DBufInfo->buffers[cmd.shape2DBufIndex]; + state.SetVertexBuffer(buffers.GetBufferObjects().first); + state.SetIndexBuffer(buffers.GetBufferObjects().second); state.DrawIndexed(DT_Triangles, 0, cmd.shape2DIndexCount); - state.SetVertexBuffer(&vb); + state.SetVertexBuffer(vb.GetBufferObjects().first); + state.SetVertexBuffer(vb.GetBufferObjects().second); if (cmd.shape2DCommandCounter == cmd.shape2DBufInfo->lastCommand) { cmd.shape2DBufInfo->lastCommand = -1; @@ -254,7 +258,7 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int state.SetScissor(-1, -1, -1, -1); state.SetRenderStyle(STYLE_Translucent); - state.SetVertexBuffer(screen->mVertexData); + state.SetFlatVertexBuffer(); state.EnableStencil(false); state.SetStencil(0, SOP_Keep, SF_AllOn); state.EnableTexture(true); diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index 3772a4f8c..5b940d25f 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -50,7 +50,6 @@ struct FPortalSceneState; class FSkyVertexBuffer; class IBuffer; -class FFlatVertexBuffer; struct HWDrawInfo; class FMaterial; class FGameTexture; @@ -137,7 +136,6 @@ public: unsigned int maxuniformblock = 65536; 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 ShadowMap* mShadowMap = nullptr; int mGameScreenWidth = 0; diff --git a/src/common/rendering/vulkan/buffers/vk_buffer.cpp b/src/common/rendering/vulkan/buffers/vk_buffer.cpp index d2422e7e9..4f90a26d8 100644 --- a/src/common/rendering/vulkan/buffers/vk_buffer.cpp +++ b/src/common/rendering/vulkan/buffers/vk_buffer.cpp @@ -27,6 +27,7 @@ #include "vulkan/pipelines/vk_renderpass.h" #include "vulkan/commands/vk_commandbuffer.h" #include +#include "flatvertices.h" VkBufferManager::VkBufferManager(VulkanRenderDevice* fb) : fb(fb) { @@ -38,6 +39,32 @@ VkBufferManager::~VkBufferManager() void VkBufferManager::Init() { + static const FVertexBufferAttribute format[] = + { + { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) }, + { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }, + { 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FFlatVertex, lu) }, + }; + + Flatbuffer.VertexFormat = fb->GetRenderPassManager()->GetVertexFormat(1, 3, sizeof(FFlatVertex), format); + + Flatbuffer.VertexBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT) + .MemoryType( + 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) + .Size(Flatbuffer.BUFFER_SIZE * sizeof(FFlatVertex)) + .DebugName("Flatbuffer.VertexBuffer") + .Create(fb->GetDevice()); + + Flatbuffer.Vertices = (FFlatVertex*)Flatbuffer.VertexBuffer->Map(0, Flatbuffer.VertexBuffer->size); + + Flatbuffer.IndexBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY) + .Size(16) + .DebugName("Flatbuffer.IndexBuffer") + .Create(fb->GetDevice()); + MatrixBuffer.reset(new VkStreamBuffer(this, sizeof(MatricesUBO), 50000)); StreamBuffer.reset(new VkStreamBuffer(this, sizeof(StreamUBO), 300)); @@ -85,6 +112,11 @@ void VkBufferManager::Init() void VkBufferManager::Deinit() { + if (Flatbuffer.VertexBuffer) + Flatbuffer.VertexBuffer->Unmap(); + Flatbuffer.VertexBuffer.reset(); + Flatbuffer.IndexBuffer.reset(); + if (Viewpoint.UBO) Viewpoint.UBO->Unmap(); Viewpoint.UBO.reset(); diff --git a/src/common/rendering/vulkan/buffers/vk_buffer.h b/src/common/rendering/vulkan/buffers/vk_buffer.h index b6476d818..5465a33b9 100644 --- a/src/common/rendering/vulkan/buffers/vk_buffer.h +++ b/src/common/rendering/vulkan/buffers/vk_buffer.h @@ -11,6 +11,7 @@ class VkStreamBuffer; class IBuffer; struct FVertexBufferAttribute; struct HWViewpointUniforms; +struct FFlatVertex; class VkBufferManager { @@ -27,6 +28,18 @@ public: void AddBuffer(VkHardwareBuffer* buffer); void RemoveBuffer(VkHardwareBuffer* buffer); + struct + { + std::unique_ptr VertexBuffer; + int VertexFormat = 0; + FFlatVertex* Vertices = nullptr; + unsigned int ShadowDataSize = 0; + unsigned int CurIndex = 0; + static const unsigned int BUFFER_SIZE = 2000000; + static const unsigned int BUFFER_SIZE_TO_USE = BUFFER_SIZE - 500; + std::unique_ptr IndexBuffer; + } Flatbuffer; + struct { int UploadIndex = 0; diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index b9479cbdd..351a5eaae 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -129,7 +129,6 @@ VulkanRenderDevice::~VulkanRenderDevice() { vkDeviceWaitIdle(mDevice->device); // make sure the GPU is no longer using any objects before RAII tears them down - delete mVertexData; delete mSkyData; delete mShadowMap; @@ -174,7 +173,6 @@ void VulkanRenderDevice::InitializeState() mTextureManager.reset(new VkTextureManager(this)); mFramebufferManager.reset(new VkFramebufferManager(this)); mBufferManager.reset(new VkBufferManager(this)); - mBufferManager->Init(); mScreenBuffers.reset(new VkRenderBuffers(this)); mSaveBuffers.reset(new VkRenderBuffers(this)); @@ -185,7 +183,8 @@ void VulkanRenderDevice::InitializeState() mRenderPassManager.reset(new VkRenderPassManager(this)); mRaytrace.reset(new VkRaytrace(this)); - mVertexData = new FFlatVertexBuffer(this, GetWidth(), GetHeight()); + mBufferManager->Init(); + mSkyData = new FSkyVertexBuffer(this); mShadowMap = new ShadowMap(this); diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 52c08eecb..84586605b 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -224,7 +224,7 @@ void VkRenderState::ApplyRenderPass(int dt) // Find a pipeline that matches our state VkPipelineKey pipelineKey; pipelineKey.DrawType = dt; - pipelineKey.VertexFormat = static_cast(mVertexBuffer)->VertexFormat; + pipelineKey.VertexFormat = mVertexBuffer ? static_cast(mVertexBuffer)->VertexFormat : fb->GetBufferManager()->Flatbuffer.VertexFormat; pipelineKey.RenderStyle = mRenderStyle; pipelineKey.DepthTest = mDepthTest; pipelineKey.DepthWrite = mDepthTest && mDepthWrite; @@ -394,7 +394,7 @@ void VkRenderState::ApplyStreamData() { auto passManager = fb->GetRenderPassManager(); - mStreamData.useVertexData = passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData; + mStreamData.useVertexData = mVertexBuffer ? passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData : 0; if (mMaterial.mMaterial && mMaterial.mMaterial->Source()) mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->GetShaderSpeed() / 1000.); @@ -439,22 +439,42 @@ void VkRenderState::ApplyMatrices() void VkRenderState::ApplyVertexBuffers() { - if ((mVertexBuffer != mLastVertexBuffer || mVertexOffsets[0] != mLastVertexOffsets[0] || mVertexOffsets[1] != mLastVertexOffsets[1]) && mVertexBuffer) + if ((mVertexBuffer != mLastVertexBuffer || mVertexOffsets[0] != mLastVertexOffsets[0] || mVertexOffsets[1] != mLastVertexOffsets[1])) { - auto vkbuf = static_cast(mVertexBuffer); - const VkVertexFormat *format = fb->GetRenderPassManager()->GetVertexFormat(vkbuf->VertexFormat); - VkBuffer vertexBuffers[2] = { vkbuf->mBuffer->buffer, vkbuf->mBuffer->buffer }; - VkDeviceSize offsets[] = { mVertexOffsets[0] * format->Stride, mVertexOffsets[1] * format->Stride }; - mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, offsets); + if (mVertexBuffer) + { + auto vkbuf = static_cast(mVertexBuffer); + const VkVertexFormat* format = fb->GetRenderPassManager()->GetVertexFormat(vkbuf->VertexFormat); + VkBuffer vertexBuffers[2] = { vkbuf->mBuffer->buffer, vkbuf->mBuffer->buffer }; + VkDeviceSize offsets[] = { mVertexOffsets[0] * format->Stride, mVertexOffsets[1] * format->Stride }; + mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, offsets); + } + else + { + auto buffers = fb->GetBufferManager(); + const VkVertexFormat* format = fb->GetRenderPassManager()->GetVertexFormat(buffers->Flatbuffer.VertexFormat); + VkBuffer vertexBuffers[2] = { buffers->Flatbuffer.VertexBuffer->buffer, buffers->Flatbuffer.VertexBuffer->buffer }; + VkDeviceSize offsets[] = { mVertexOffsets[0] * format->Stride, mVertexOffsets[1] * format->Stride }; + mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, offsets); + } + mLastVertexBuffer = mVertexBuffer; mLastVertexOffsets[0] = mVertexOffsets[0]; mLastVertexOffsets[1] = mVertexOffsets[1]; } - if (mIndexBuffer != mLastIndexBuffer && mIndexBuffer) + if (mIndexBuffer != mLastIndexBuffer || mIndexBufferNeedsBind) { - mCommandBuffer->bindIndexBuffer(static_cast(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32); + if (mIndexBuffer) + { + mCommandBuffer->bindIndexBuffer(static_cast(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32); + } + else + { + mCommandBuffer->bindIndexBuffer(fb->GetBufferManager()->Flatbuffer.IndexBuffer->buffer, 0, VK_INDEX_TYPE_UINT32); + } mLastIndexBuffer = mIndexBuffer; + mIndexBufferNeedsBind = false; } } @@ -622,35 +642,77 @@ int VkRenderState::UploadBones(const TArray& bones) std::pair VkRenderState::AllocVertices(unsigned int count) { - return fb->mVertexData->AllocVertices(count); + auto buffers = fb->GetBufferManager(); + unsigned int index = buffers->Flatbuffer.CurIndex; + if (index + count >= buffers->Flatbuffer.BUFFER_SIZE_TO_USE) + { + // If a single scene needs 2'000'000 vertices there must be something very wrong. + I_FatalError("Out of vertex memory. Tried to allocate more than %u vertices for a single frame", index + count); + } + buffers->Flatbuffer.CurIndex += count; + return std::make_pair(buffers->Flatbuffer.Vertices + index, index); } void VkRenderState::SetShadowData(const TArray& vertices, const TArray& indexes) { - FFlatVertexBuffer* fvb = fb->mVertexData; - fvb->vbo_shadowdata = vertices; - fvb->ibo_data = indexes; - fvb->mCurIndex = fvb->vbo_shadowdata.Size(); - 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], BufferUsageType::Static); + auto buffers = fb->GetBufferManager(); + auto commands = fb->GetCommands(); + + UpdateShadowData(0, vertices.Data(), vertices.Size()); + buffers->Flatbuffer.ShadowDataSize = vertices.Size(); + buffers->Flatbuffer.CurIndex = buffers->Flatbuffer.ShadowDataSize; + + if (indexes.Size() > 0) + { + size_t bufsize = indexes.Size() * sizeof(uint32_t); + + auto buffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY) + .Size(bufsize) + .DebugName("Flatbuffer.IndexBuffer") + .Create(fb->GetDevice()); + + auto staging = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(bufsize) + .DebugName("Flatbuffer.IndexBuffer.Staging") + .Create(fb->GetDevice()); + + void* dst = staging->Map(0, bufsize); + memcpy(dst, indexes.Data(), bufsize); + staging->Unmap(); + + commands->GetTransferCommands()->copyBuffer(staging.get(), buffer.get()); + commands->TransferDeleteList->Add(std::move(staging)); + + commands->DrawDeleteList->Add(std::move(buffers->Flatbuffer.IndexBuffer)); + buffers->Flatbuffer.IndexBuffer = std::move(buffer); + + mIndexBufferNeedsBind = true; + mNeedApply = true; + } } void VkRenderState::UpdateShadowData(unsigned int index, const FFlatVertex* vertices, unsigned int count) { - FFlatVertexBuffer* fvb = fb->mVertexData; - FFlatVertex* mapvt = fvb->GetBuffer(index); - memcpy(mapvt, vertices, count * sizeof(FFlatVertex)); - fvb->mVertexBuffer->Upload(index * sizeof(FFlatVertex), count * sizeof(FFlatVertex)); + memcpy(fb->GetBufferManager()->Flatbuffer.Vertices + index, vertices, count * sizeof(FFlatVertex)); +} + +void VkRenderState::ResetVertices() +{ + auto buffers = fb->GetBufferManager(); + buffers->Flatbuffer.CurIndex = buffers->Flatbuffer.ShadowDataSize; } void VkRenderState::BeginFrame() { mMaterial.Reset(); mApplyCount = 0; - fb->GetBufferManager()->Viewpoint.UploadIndex = 0; - fb->GetBufferManager()->Lightbuffer.UploadIndex = 0; - fb->GetBufferManager()->Bonebuffer.UploadIndex = 0; + + auto buffers = fb->GetBufferManager(); + buffers->Viewpoint.UploadIndex = 0; + buffers->Lightbuffer.UploadIndex = 0; + buffers->Bonebuffer.UploadIndex = 0; } void VkRenderState::EndRenderPass() @@ -661,9 +723,10 @@ void VkRenderState::EndRenderPass() mCommandBuffer = nullptr; mPipelineKey = {}; + // Force rebind of all buffers mLastViewpointOffset = 0xffffffff; - mLastVertexBuffer = nullptr; - mLastIndexBuffer = nullptr; + mLastVertexOffsets[0] = 0xffffffff; + mIndexBufferNeedsBind = true; } } diff --git a/src/common/rendering/vulkan/vk_renderstate.h b/src/common/rendering/vulkan/vk_renderstate.h index 7b90b6573..deb06d8f5 100644 --- a/src/common/rendering/vulkan/vk_renderstate.h +++ b/src/common/rendering/vulkan/vk_renderstate.h @@ -59,6 +59,7 @@ public: std::pair AllocVertices(unsigned int count) override; void SetShadowData(const TArray& vertices, const TArray& indexes) override; void UpdateShadowData(unsigned int index, const FFlatVertex* vertices, unsigned int count) override; + void ResetVertices() override; protected: void Apply(int dt); @@ -117,6 +118,7 @@ protected: int mLastVertexOffsets[2] = { 0, 0 }; IBuffer* mLastVertexBuffer = nullptr; IBuffer* mLastIndexBuffer = nullptr; + bool mIndexBufferNeedsBind = true; MatricesUBO mMatrices = {}; bool mMatricesChanged = true; diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index e863e6d22..47e7286c1 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -275,8 +275,8 @@ void WriteSavePic(player_t* player, FileWriter* file, int width, int height) hw_postprocess.SetTonemapMode(level.info ? level.info->tonemap : ETonemapMode::None); hw_ClearFakeFlat(); - screen->mVertexData->Reset(); - RenderState.SetVertexBuffer(screen->mVertexData); + RenderState.ResetVertices(); + RenderState.SetFlatVertexBuffer(); // This shouldn't overwrite the global viewpoint even for a short time. FRenderViewpoint savevp; @@ -313,8 +313,8 @@ static void CheckTimer(FRenderState &state, uint64_t ShaderStartTime) sector_t* RenderView(player_t* player) { auto RenderState = screen->RenderState(); - RenderState->SetVertexBuffer(screen->mVertexData); - screen->mVertexData->Reset(); + RenderState->SetFlatVertexBuffer(); + RenderState->ResetVertices(); hw_postprocess.SetTonemapMode(level.info ? level.info->tonemap : ETonemapMode::None); sector_t* retsec; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 8d187a36a..39c65fc88 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -446,7 +446,6 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) ProcessAll.Clock(); // clip the scene and fill the drawlists - screen->mVertexData->Map(); if (!gl_meshcache) RenderBSP(Level->HeadNode(), drawpsprites, state); @@ -459,7 +458,6 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) HandleHackedSubsectors(state); // open sector hacks for deep water PrepareUnhandledMissingTextures(state); DispatchRenderHacks(state); - screen->mVertexData->Unmap(); ProcessAll.Unclock(); @@ -589,7 +587,7 @@ void HWDrawInfo::RenderPortal(HWPortal *p, FRenderState &state, bool usestencil) state.SetLightIndex(-1); gp->DrawContents(new_di, state); new_di->EndDrawInfo(); - state.SetVertexBuffer(screen->mVertexData); + state.SetFlatVertexBuffer(); state.SetViewpoint(vpIndex); gp->RemoveStencil(this, state, usestencil); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 6996c54ec..268231e76 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -32,7 +32,6 @@ struct HUDSprite; class ACorona; class Clipper; class HWPortal; -class FFlatVertexBuffer; class HWScenePortalBase; class FRenderState; diff --git a/src/rendering/hwrenderer/scene/hw_drawlist.cpp b/src/rendering/hwrenderer/scene/hw_drawlist.cpp index 37930fef5..9d524034c 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlist.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawlist.cpp @@ -939,9 +939,7 @@ void HWDrawList::DrawSorted(HWDrawInfo *di, FRenderState &state) if (!sorted) { - screen->mVertexData->Map(); Sort(di, state); - screen->mVertexData->Unmap(); } state.ClearClipSplit(); DrawSorted(di, state, sorted); diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 2b35acdfe..338948786 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -191,7 +191,6 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass) if (NeedCap() && lines.Size() > 1 && planesused != 0) { - screen->mVertexData->Map(); if (planesused & (1 << sector_t::floor)) { auto verts = state.AllocVertices(4); @@ -212,7 +211,6 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass) ptr[3].Set((float)boundingBox.right, 32767.f, (float)boundingBox.bottom, 0, 0); mTopCap = verts.second; } - screen->mVertexData->Unmap(); } } diff --git a/src/rendering/hwrenderer/scene/hw_skyportal.cpp b/src/rendering/hwrenderer/scene/hw_skyportal.cpp index 7000cd8b9..386b8fc1f 100644 --- a/src/rendering/hwrenderer/scene/hw_skyportal.cpp +++ b/src/rendering/hwrenderer/scene/hw_skyportal.cpp @@ -58,7 +58,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) di->SetupView(state, 0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1)); - state.SetVertexBuffer(vertexBuffer); + state.SetVertexBuffer(vertexBuffer->mVertexBuffer); auto skybox = origin->texture[0] ? dynamic_cast(origin->texture[0]->GetTexture()) : nullptr; if (skybox) { diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index ee2912d4e..870e4a502 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -300,7 +300,7 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) { FHWModelRenderer renderer(di, state, dynlightindex); RenderModel(&renderer, x, y, z, modelframe, actor, di->Viewpoint.TicFrac); - state.SetVertexBuffer(screen->mVertexData); + state.SetFlatVertexBuffer(); state.SetLightIndex(-1); } } diff --git a/src/rendering/hwrenderer/scene/hw_weapon.cpp b/src/rendering/hwrenderer/scene/hw_weapon.cpp index 26f9f1296..c2588c9d0 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.cpp +++ b/src/rendering/hwrenderer/scene/hw_weapon.cpp @@ -89,7 +89,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state) FHWModelRenderer renderer(this, state, huds->lightindex); RenderHUDModel(&renderer, huds->weapon, huds->translation, huds->rotation + FVector3(huds->mx / 4., (huds->my - WEAPONTOP) / -4., 0), huds->pivot, huds->mframe); - state.SetVertexBuffer(screen->mVertexData); + state.SetFlatVertexBuffer(); } else {