diff --git a/src/rendering/gl/renderer/gl_renderbuffers.cpp b/src/rendering/gl/renderer/gl_renderbuffers.cpp index 0d0f6a3921..a54df1279a 100644 --- a/src/rendering/gl/renderer/gl_renderbuffers.cpp +++ b/src/rendering/gl/renderer/gl_renderbuffers.cpp @@ -955,7 +955,7 @@ void GLPPRenderState::Draw() if (Uniforms.Data.Size() > 0) { if (!shader->Uniforms) - shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false)); + shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false, false)); shader->Uniforms->SetData(Uniforms.Data.Size(), Uniforms.Data.Data()); shader->Uniforms->BindBase(); } diff --git a/src/rendering/gl/system/gl_framebuffer.cpp b/src/rendering/gl/system/gl_framebuffer.cpp index d5a00b72a6..b0b33faca4 100644 --- a/src/rendering/gl/system/gl_framebuffer.cpp +++ b/src/rendering/gl/system/gl_framebuffer.cpp @@ -339,7 +339,7 @@ IIndexBuffer *OpenGLFrameBuffer::CreateIndexBuffer() return new GLIndexBuffer; } -IDataBuffer *OpenGLFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo) +IDataBuffer *OpenGLFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) { return new GLDataBuffer(bindingpoint, ssbo); } diff --git a/src/rendering/gl/system/gl_framebuffer.h b/src/rendering/gl/system/gl_framebuffer.h index 19bc192d12..f20c796d1c 100644 --- a/src/rendering/gl/system/gl_framebuffer.h +++ b/src/rendering/gl/system/gl_framebuffer.h @@ -39,7 +39,7 @@ public: void BlurScene(float amount) override; IVertexBuffer *CreateVertexBuffer() override; IIndexBuffer *CreateIndexBuffer() override; - IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo) override; + IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer diff --git a/src/rendering/hwrenderer/data/hw_viewpointbuffer.cpp b/src/rendering/hwrenderer/data/hw_viewpointbuffer.cpp index 39a9ad6515..f916e8213f 100644 --- a/src/rendering/hwrenderer/data/hw_viewpointbuffer.cpp +++ b/src/rendering/hwrenderer/data/hw_viewpointbuffer.cpp @@ -38,7 +38,7 @@ GLViewpointBuffer::GLViewpointBuffer() mBufferSize = INITIAL_BUFFER_SIZE; mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment; mByteSize = mBufferSize * mBlockAlign; - mBuffer = screen->CreateDataBuffer(VIEWPOINT_BINDINGPOINT, false); + mBuffer = screen->CreateDataBuffer(VIEWPOINT_BINDINGPOINT, false, true); mBuffer->SetData(mByteSize, nullptr, false); Clear(); mLastMappedIndex = UINT_MAX; diff --git a/src/rendering/hwrenderer/data/shaderuniforms.h b/src/rendering/hwrenderer/data/shaderuniforms.h index 8937b6fb78..636f41aea5 100644 --- a/src/rendering/hwrenderer/data/shaderuniforms.h +++ b/src/rendering/hwrenderer/data/shaderuniforms.h @@ -123,7 +123,7 @@ public: void Init() { if (mBuffer == nullptr) - mBuffer = screen->CreateDataBuffer(bindingpoint, false); + mBuffer = screen->CreateDataBuffer(bindingpoint, false, false); } void Set(bool bind = true) diff --git a/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp b/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp index bb7c78e9bd..8dfb48f0ce 100644 --- a/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp +++ b/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp @@ -60,7 +60,7 @@ FLightBuffer::FLightBuffer() mByteSize += screen->maxuniformblock; // to avoid mapping beyond the end of the buffer. } - mBuffer = screen->CreateDataBuffer(LIGHTBUF_BINDINGPOINT, mBufferType); + mBuffer = screen->CreateDataBuffer(LIGHTBUF_BINDINGPOINT, mBufferType, false); mBuffer->SetData(mByteSize, nullptr, false); Clear(); diff --git a/src/rendering/hwrenderer/dynlights/hw_shadowmap.cpp b/src/rendering/hwrenderer/dynlights/hw_shadowmap.cpp index 2ae3cb092a..a005812ba9 100644 --- a/src/rendering/hwrenderer/dynlights/hw_shadowmap.cpp +++ b/src/rendering/hwrenderer/dynlights/hw_shadowmap.cpp @@ -189,7 +189,7 @@ void IShadowMap::UploadLights() CollectLights(); if (mLightList == nullptr) - mLightList = screen->CreateDataBuffer(LIGHTLIST_BINDINGPOINT, true); + mLightList = screen->CreateDataBuffer(LIGHTLIST_BINDINGPOINT, true, false); mLightList->SetData(sizeof(float) * mLights.Size(), &mLights[0]); } @@ -200,11 +200,11 @@ void IShadowMap::UploadAABBTree() if (!ValidateAABBTree(&level)) { if (!mNodesBuffer) - mNodesBuffer = screen->CreateDataBuffer(LIGHTNODES_BINDINGPOINT, true); + mNodesBuffer = screen->CreateDataBuffer(LIGHTNODES_BINDINGPOINT, true, false); mNodesBuffer->SetData(mAABBTree->NodesSize(), mAABBTree->Nodes()); if (!mLinesBuffer) - mLinesBuffer = screen->CreateDataBuffer(LIGHTLINES_BINDINGPOINT, true); + mLinesBuffer = screen->CreateDataBuffer(LIGHTLINES_BINDINGPOINT, true, false); mLinesBuffer->SetData(mAABBTree->LinesSize(), mAABBTree->Lines()); } else if (mAABBTree->Update()) diff --git a/src/rendering/vulkan/system/vk_buffers.cpp b/src/rendering/vulkan/system/vk_buffers.cpp index 1dd36f9706..59b59b7dea 100644 --- a/src/rendering/vulkan/system/vk_buffers.cpp +++ b/src/rendering/vulkan/system/vk_buffers.cpp @@ -111,7 +111,30 @@ void VKBuffer::SetSubData(size_t offset, size_t size, const void *data) void VKBuffer::Resize(size_t newsize) { - I_FatalError("VKBuffer::Resize not implemented\n"); + auto fb = GetVulkanFrameBuffer(); + + // Grab old buffer + size_t oldsize = buffersize; + std::unique_ptr oldBuffer = std::move(mBuffer); + oldBuffer->Unmap(); + map = nullptr; + + // Create new buffer + BufferBuilder builder; + builder.setUsage(mBufferType, VMA_MEMORY_USAGE_CPU_TO_GPU, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT); + builder.setSize(newsize); + mBuffer = builder.create(fb->device); + buffersize = newsize; + + // Transfer data from old to new + fb->GetTransferCommands()->copyBuffer(oldBuffer.get(), mBuffer.get(), 0, 0, oldsize); + fb->SubmitCommands(false); + + // Fetch pointer to new buffer + map = mBuffer->Map(0, newsize); + + // Old buffer may be part of the dynamic set + fb->GetRenderPassManager()->UpdateDynamicSet(); } void VKBuffer::Map() diff --git a/src/rendering/vulkan/system/vk_buffers.h b/src/rendering/vulkan/system/vk_buffers.h index df99cf1c0d..57ab7d9230 100644 --- a/src/rendering/vulkan/system/vk_buffers.h +++ b/src/rendering/vulkan/system/vk_buffers.h @@ -57,7 +57,14 @@ public: class VKDataBuffer : public IDataBuffer, public VKBuffer { public: - VKDataBuffer(int bindingpoint, bool ssbo) : bindingpoint(bindingpoint) { mBufferType = ssbo ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; } + VKDataBuffer(int bindingpoint, bool ssbo, bool needresize) : bindingpoint(bindingpoint) + { + mBufferType = ssbo ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + if (needresize) + { + mBufferType |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + } + } void BindRange(size_t start, size_t length) override; void BindBase() override; diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index daabbf10ad..b3b7336ad9 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -138,8 +138,8 @@ void VulkanFrameBuffer::InitializeState() CreateFanToTrisIndexBuffer(); // To do: move this to HW renderer interface maybe? - MatricesUBO = (VKDataBuffer*)CreateDataBuffer(-1, false); - StreamUBO = (VKDataBuffer*)CreateDataBuffer(-1, false); + MatricesUBO = (VKDataBuffer*)CreateDataBuffer(-1, false, false); + StreamUBO = (VKDataBuffer*)CreateDataBuffer(-1, false, false); MatricesUBO->SetData(UniformBufferAlignedSize<::MatricesUBO>() * 50000, nullptr, false); StreamUBO->SetData(UniformBufferAlignedSize<::StreamUBO>() * 200, nullptr, false); @@ -590,9 +590,9 @@ IIndexBuffer *VulkanFrameBuffer::CreateIndexBuffer() return new VKIndexBuffer(); } -IDataBuffer *VulkanFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo) +IDataBuffer *VulkanFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) { - auto buffer = new VKDataBuffer(bindingpoint, ssbo); + auto buffer = new VKDataBuffer(bindingpoint, ssbo, needsresize); auto fb = GetVulkanFrameBuffer(); switch (bindingpoint) diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 05302da13f..64b357e2bf 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -86,7 +86,7 @@ public: FModelRenderer *CreateModelRenderer(int mli) override; IVertexBuffer *CreateVertexBuffer() override; IIndexBuffer *CreateIndexBuffer() override; - IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo) override; + IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; FTexture *WipeStartScreen() override; FTexture *WipeEndScreen() override; @@ -97,13 +97,14 @@ public: void Draw2D() override; + void SubmitCommands(bool finish); + private: sector_t *RenderViewpoint(FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); void DrawScene(HWDrawInfo *di, int drawmode); void PrintStartupLog(); void CreateFanToTrisIndexBuffer(); - void SubmitCommands(bool finish); void CopyScreenToBuffer(int w, int h, void *data); void UpdateShadowMap(); void DeleteFrameObjects(); diff --git a/src/v_video.h b/src/v_video.h index 9f682f2467..4c0597c4f4 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -448,7 +448,7 @@ public: // Interface to hardware rendering resources virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; } virtual IIndexBuffer *CreateIndexBuffer() { return nullptr; } - virtual IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo) { return nullptr; } + virtual IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) { return nullptr; } bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); } // Begin/End 2D drawing operations.