diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 39e2d8bebb..ca64ae4e11 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -171,9 +171,9 @@ void DrawEngineVulkan::InitDeviceObjects() { // Note that pushUBO is also used for tessellation data (search for SetPushBuffer), and to upload // the null texture. This should be cleaned up... - frame_[i].pushUBO = new VulkanPushBuffer(vulkan, "pushUBO", 8 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, PushBufferType::CPU_TO_GPU); } + pushUBO = new VulkanPushPool(vulkan, "pushUBO", 4 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT); pushVertex = new VulkanPushPool(vulkan, "pushVertex", 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); pushIndex = new VulkanPushPool(vulkan, "pushIndex", 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); @@ -222,12 +222,6 @@ DrawEngineVulkan::~DrawEngineVulkan() { void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) { descPool.Destroy(); - - if (pushUBO) { - pushUBO->Destroy(vulkan); - delete pushUBO; - pushUBO = nullptr; - } } void DrawEngineVulkan::DestroyDeviceObjects() { @@ -258,6 +252,12 @@ void DrawEngineVulkan::DestroyDeviceObjects() { delete pushIndex; pushIndex = nullptr; } + if (pushUBO) { + pushUBO->Destroy(); + delete pushUBO; + pushUBO = nullptr; + } + if (samplerSecondaryNearest_ != VK_NULL_HANDLE) vulkan->Delete().QueueDeleteSampler(samplerSecondaryNearest_); if (samplerSecondaryLinear_ != VK_NULL_HANDLE) @@ -297,25 +297,22 @@ void DrawEngineVulkan::BeginFrame() { lastPipeline_ = nullptr; + pushUBO->BeginFrame(); + pushVertex->BeginFrame(); + pushIndex->BeginFrame(); + + tessDataTransferVulkan->SetPushPool(pushUBO); + + DirtyAllUBOs(); + FrameData *frame = &GetCurFrame(); // First reset all buffers, then begin. This is so that Reset can free memory and Begin can allocate it, // if growing the buffer is needed. Doing it this way will reduce fragmentation if more than one buffer // needs to grow in the same frame. The state where many buffers are reset can also be used to // defragment memory. - frame->pushUBO->Reset(); - VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - frame->pushUBO->Begin(vulkan); - - pushVertex->BeginFrame(); - pushIndex->BeginFrame(); - - tessDataTransferVulkan->SetPushBuffer(frame->pushUBO); - - DirtyAllUBOs(); - // Wipe the vertex cache if it's grown too large. if (vertexCache_->GetTotalSize() > VERTEX_CACHE_SIZE) { vertexCache_->Destroy(vulkan); @@ -360,10 +357,9 @@ void DrawEngineVulkan::BeginFrame() { void DrawEngineVulkan::EndFrame() { FrameData *frame = &GetCurFrame(); - stats_.pushUBOSpaceUsed = (int)frame->pushUBO->GetOffset(); + stats_.pushUBOSpaceUsed = 0; // (int)pushUBO->GetOffset(); stats_.pushVertexSpaceUsed = 0; // (int)frame->pushVertex->GetOffset(); stats_.pushIndexSpaceUsed = 0; // (int)frame->pushIndex->GetOffset(); - frame->pushUBO->End(); vertexCache_->End(); } @@ -1042,15 +1038,15 @@ void DrawEngineVulkan::DoFlush() { void DrawEngineVulkan::UpdateUBOs(FrameData *frame) { if ((dirtyUniforms_ & DIRTY_BASE_UNIFORMS) || baseBuf == VK_NULL_HANDLE) { - baseUBOOffset = shaderManager_->PushBaseBuffer(frame->pushUBO, &baseBuf); + baseUBOOffset = shaderManager_->PushBaseBuffer(pushUBO, &baseBuf); dirtyUniforms_ &= ~DIRTY_BASE_UNIFORMS; } if ((dirtyUniforms_ & DIRTY_LIGHT_UNIFORMS) || lightBuf == VK_NULL_HANDLE) { - lightUBOOffset = shaderManager_->PushLightBuffer(frame->pushUBO, &lightBuf); + lightUBOOffset = shaderManager_->PushLightBuffer(pushUBO, &lightBuf); dirtyUniforms_ &= ~DIRTY_LIGHT_UNIFORMS; } if ((dirtyUniforms_ & DIRTY_BONE_UNIFORMS) || boneBuf == VK_NULL_HANDLE) { - boneUBOOffset = shaderManager_->PushBoneBuffer(frame->pushUBO, &boneBuf); + boneUBOOffset = shaderManager_->PushBoneBuffer(pushUBO, &boneBuf); dirtyUniforms_ &= ~DIRTY_BONE_UNIFORMS; } } @@ -1072,7 +1068,7 @@ void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const int size = size_u * size_v; int ssboAlignment = vulkan_->GetPhysicalDeviceProperties().properties.limits.minStorageBufferOffsetAlignment; - uint8_t *data = (uint8_t *)push_->PushAligned(size * sizeof(TessData), (uint32_t *)&bufInfo_[0].offset, &bufInfo_[0].buffer, ssboAlignment); + uint8_t *data = (uint8_t *)push_->Allocate(size * sizeof(TessData), ssboAlignment, &bufInfo_[0].buffer, (uint32_t *)&bufInfo_[0].offset); bufInfo_[0].range = size * sizeof(TessData); float *pos = (float *)(data); @@ -1085,12 +1081,12 @@ void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const using Spline::Weight; // Weights U - data = (uint8_t *)push_->PushAligned(weights.size_u * sizeof(Weight), (uint32_t *)&bufInfo_[1].offset, &bufInfo_[1].buffer, ssboAlignment); + data = (uint8_t *)push_->Allocate(weights.size_u * sizeof(Weight), ssboAlignment, &bufInfo_[1].buffer, (uint32_t *)&bufInfo_[1].offset); memcpy(data, weights.u, weights.size_u * sizeof(Weight)); bufInfo_[1].range = weights.size_u * sizeof(Weight); // Weights V - data = (uint8_t *)push_->PushAligned(weights.size_v * sizeof(Weight), (uint32_t *)&bufInfo_[2].offset, &bufInfo_[2].buffer, ssboAlignment); + data = (uint8_t *)push_->Allocate(weights.size_v * sizeof(Weight), ssboAlignment, &bufInfo_[2].buffer, (uint32_t *)&bufInfo_[2].offset); memcpy(data, weights.v, weights.size_v * sizeof(Weight)); bufInfo_[2].range = weights.size_v * sizeof(Weight); } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 16693d2f4c..1c209eb38f 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -113,13 +113,13 @@ class TessellationDataTransferVulkan : public TessellationDataTransfer { public: TessellationDataTransferVulkan(VulkanContext *vulkan) : vulkan_(vulkan) {} - void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; } + void SetPushPool(VulkanPushPool *push) { push_ = push; } // Send spline/bezier's control points and weights to vertex shader through structured shader buffer. void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) override; const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; } private: VulkanContext *vulkan_; - VulkanPushBuffer *push_; // Updated each frame. + VulkanPushPool *push_; // Updated each frame. VkDescriptorBufferInfo bufInfo_[3]{}; }; @@ -193,8 +193,8 @@ public: lastPipeline_ = nullptr; } - VulkanPushBuffer *GetPushBufferForTextureData() { - return GetCurFrame().pushUBO; + VulkanPushPool *GetPushBufferForTextureData() { + return pushUBO; } const DrawEngineVulkanStats &GetStats() const { @@ -270,8 +270,6 @@ private: VulkanDescSetPool descPool; - VulkanPushBuffer *pushUBO = nullptr; - // We do rolling allocation and reset instead of caching across frames. That we might do later. DenseHashMap descSets; @@ -281,6 +279,7 @@ private: GEPrimitiveType lastPrim_ = GE_PRIM_INVALID; FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES]; + VulkanPushPool *pushUBO = nullptr; VulkanPushPool *pushVertex = nullptr; VulkanPushPool *pushIndex = nullptr; diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 38b4b2e1e1..13013fa498 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -34,7 +34,7 @@ class VulkanContext; class DrawEngineVulkan; -class VulkanPushBuffer; +class VulkanPushPool; class VulkanFragmentShader { public: @@ -145,15 +145,15 @@ public: bool IsLightDirty() { return true; } bool IsBoneDirty() { return true; } - uint32_t PushBaseBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { - return dest->PushAligned(&ub_base, sizeof(ub_base), uboAlignment_, buf); + uint32_t PushBaseBuffer(VulkanPushPool *dest, VkBuffer *buf) { + return dest->Push(&ub_base, sizeof(ub_base), uboAlignment_, buf); } - uint32_t PushLightBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { - return dest->PushAligned(&ub_lights, sizeof(ub_lights), uboAlignment_, buf); + uint32_t PushLightBuffer(VulkanPushPool *dest, VkBuffer *buf) { + return dest->Push(&ub_lights, sizeof(ub_lights), uboAlignment_, buf); } // TODO: Only push half the bone buffer if we only have four bones. - uint32_t PushBoneBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { - return dest->PushAligned(&ub_bones, sizeof(ub_bones), uboAlignment_, buf); + uint32_t PushBoneBuffer(VulkanPushPool *dest, VkBuffer *buf) { + return dest->Push(&ub_bones, sizeof(ub_bones), uboAlignment_, buf); } bool LoadCacheFlags(FILE *f, DrawEngineVulkan *drawEngine); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 7f60c27d2f..a08f231cd5 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -550,7 +550,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { levels = plan.levelsToLoad; } - VulkanPushBuffer *pushBuffer = drawEngine_->GetPushBufferForTextureData(); + VulkanPushPool *pushBuffer = drawEngine_->GetPushBufferForTextureData(); // Batch the copies. TextureCopyBatch copyBatch; @@ -583,11 +583,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { saveData.resize(sz); data = &saveData[0]; } else { - data = pushBuffer->PushAligned(sz, &bufferOffset, &texBuf, pushAlignment); + data = pushBuffer->Allocate(sz, pushAlignment, &texBuf, &bufferOffset); } LoadVulkanTextureLevel(*entry, (uint8_t *)data, lstride, srcLevel, lfactor, actualFmt); if (plan.saveTexture) - bufferOffset = pushBuffer->PushAligned(&saveData[0], sz, pushAlignment, &texBuf); + bufferOffset = pushBuffer->Push(&saveData[0], sz, pushAlignment, &texBuf); }; bool dataScaled = true; @@ -599,7 +599,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { rowLength = (mipWidth + 3) & ~3; } // Directly load the replaced image. - data = pushBuffer->PushAligned(uploadSize, &bufferOffset, &texBuf, pushAlignment); + data = pushBuffer->Allocate(uploadSize, pushAlignment, &texBuf, &bufferOffset); double replaceStart = time_now_d(); if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, data, byteStride)) { // If plan.replaceValid, this shouldn't fail. WARN_LOG(G3D, "Failed to copy replaced texture level");