Вулкан продолжает потреблять все больше и больше памяти [закрыто]C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Вулкан продолжает потреблять все больше и больше памяти [закрыто]

Сообщение Anonymous »

В настоящее время я пытаюсь изменить программу Vulkan-Tutorial в рендерерал для моего игрового двигателя, но столкнулся с проблемами, когда мой рендерин медленно потребляет постоянно растущее количество оперативной памяти с течением времени, особенно если я рендеринг тысячи сетей ( Все они являются экземплярами одной и той же сетки на данный момент). < /p>
Прилагается мой код рендеринга (вся инициализация и другие не связанные материалы опущены): < /p>
const int MAX_FRAMES_IN_FLIGHT = 2;

void VulkanRenderer::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

VkResult result = vkBeginCommandBuffer(commandBuffer, &beginInfo);

if (result != VK_SUCCESS) {
throw std::runtime_error("Failed to begin recording command buffer!");
}

VkRenderPassBeginInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = app.renderPass;
renderPassInfo.framebuffer = app.swapChainFramebuffers[imageIndex];
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent = app.swapChainExtent;

std::array clearValues = {};
clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } };
clearValues[1].depthStencil = { 1.0f, 0 };

renderPassInfo.clearValueCount = static_cast(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();

vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, app.graphicsPipeline);

// Bind the global UBO descriptor set (set 0) for view/projection
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
app.pipelineLayout, 0, 1, &app.globalDescriptorSets[imageIndex],
0, nullptr);

// Iterate over all objects with a MeshComponent and Transform
// This is basically a wrapper for entt's registry.view() function
ObjectManager::Instance().forEachObjectWithComponents([&](MeshComponent& meshComp, Transform& transform) {
// Retrieve (or create) the mesh buffer. (Assumes that AssetManager::meshCache contains a Mesh for meshComp.uuid.)
Mesh& mesh = AssetManager::Instance().meshCache[meshComp.uuid];
VulkanMeshBuffer* meshBuffer = CreateMeshBuffer(meshComp.uuid, mesh);

// Bind vertex and index buffers
VkBuffer vertexBuffers[] = { meshBuffer->vertexBuffer };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, meshBuffer->indexBuffer, 0, VK_INDEX_TYPE_UINT32);

// Retrieve texture resources for this object’s texture and bind them (set 1)
TextureResource* texRes = getTextureResource(meshComp.TextureUUID);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
app.pipelineLayout, 1, 1, &texRes->descriptorSet,
0, nullptr);

// Compute the model matrix from the Transform component:
glm::mat4 model = glm::translate(glm::mat4(1.0f), transform.position);
model = glm::rotate(model, transform.rotation.x, glm::vec3(1, 0, 0));
model = glm::rotate(model, transform.rotation.y, glm::vec3(0, 1, 0));
model = glm::rotate(model, transform.rotation.z, glm::vec3(0, 0, 1));
model = glm::scale(model, transform.scale);

// Push the model matrix as a push constant (the range was set in the pipeline layout)
vkCmdPushConstants(commandBuffer, app.pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &model);

// Issue the draw call (using the index count from the mesh)
vkCmdDrawIndexed(commandBuffer, static_cast(mesh.indices.size()), 1, 0, 0, 0);
});

vkCmdEndRenderPass(commandBuffer);

result = vkEndCommandBuffer(commandBuffer);

if (result != VK_SUCCESS) {
throw VulkanError("Failed to record command buffer!", result);
}
}

void VulkanRenderer::updateUniformBuffer(uint32_t currentImage) {
GlobalUBO ubo = {};
ubo.view = glm::lookAt(glm::vec3(10.0f, 10.0f, 10.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
ubo.proj = glm::perspective(glm::radians(45.0f),
app.swapChainExtent.width / (float)app.swapChainExtent.height,
0.001f, 1000.0f);
ubo.proj[1][1] *= -1; // Flip Y-axis for Vulkan

void* data;
vkMapMemory(app.device, app.uniformBuffersMemory[currentImage], 0, sizeof(ubo), 0, &data);
memcpy(data, &ubo, sizeof(ubo));
vkUnmapMemory(app.device, app.uniformBuffersMemory[currentImage]);
}

void VulkanRenderer::drawFrame() {
vkWaitForFences(app.device, 1, &app.inFlightFences[app.currentFrame], VK_TRUE, UINT64_MAX);
vkResetFences(app.device, 1, &app.inFlightFences[app.currentFrame]);

uint32_t imageIndex;
vkAcquireNextImageKHR(app.device, app.swapChain, UINT64_MAX, app.imageAvailableSemaphores[app.currentFrame], VK_NULL_HANDLE, &imageIndex);

// Update the uniform buffer for the current image
updateUniformBuffer(imageIndex);

// Check if a previous frame is still using this image
if (app.imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
vkWaitForFences(app.device, 1, &app.imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
}

// Mark the image as now being in use by this frame
app.imagesInFlight[imageIndex] = app.inFlightFences[app.currentFrame];

// Re-record the command buffer for this frame.
vkResetCommandBuffer(app.commandBuffers[imageIndex], 0);
recordCommandBuffer(app.commandBuffers[imageIndex], imageIndex);

VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

VkSemaphore waitSemaphores[] = { app.imageAvailableSemaphores[app.currentFrame] };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;

submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &app.commandBuffers[imageIndex];

VkSemaphore signalSemaphores[] = { app.renderFinishedSemaphores[app.currentFrame] };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;

if (vkQueueSubmit(app.graphicsQueue, 1, &submitInfo, app.inFlightFences[app.currentFrame]) != VK_SUCCESS) {
throw std::runtime_error("Failed to submit draw command buffer!");
}

VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;

VkSwapchainKHR swapChains[] = { app.swapChain };
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;

VkResult result = vkQueuePresentKHR(app.presentQueue, &presentInfo);

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || app.framebufferResized) {
app.framebufferResized = false; // Reset the resize flag
recreateSwapChain(); // Recreate the swap chain when necessary
}
else if (result != VK_SUCCESS) {
throw std::runtime_error("Failed to present swap chain image!");
}

app.currentFrame = (app.currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}

void VulkanRenderer::Update()
{
last_frame_elapsed += Engine::Instance().GetDeltaTime();

if (last_frame_elapsed >= frame_time) {
drawFrame();
vkDeviceWaitIdle(app.device); // Wait until GPU finishes rendering
last_frame_elapsed = 0.0;
}
}
< /code>
Я где -то испортил? Потому что я не могу выяснить, какая часть моей программы сочетает память. На данный момент загружает модели < /p>
ObjectManager < /p>
#pragma once
#include "entt/entt.hpp"
#include
#include
#include "UUID.h"
#include "Object.h"

class ObjectManager {
public:
static ObjectManager& Instance();

ObjectManager(const ObjectManager&) = delete;
ObjectManager& operator=(const ObjectManager&) = delete;

// Method to create a new Object
Object createObject(const std::string& name);

template
void forEachObjectWithComponents(std::function func)
{
registry.view().each(func);
}

// Get all objects that have the following components
template
std::vector getObjectsWithComponents() {
std::vector objects;

for (auto entity : registry.view()) {
Object o;
o.entity_id = entity;
objects.push_back(o);
}
return objects;
}

// Method to remove an Object
void removeObject(Object obj);

// Component management with EnTT
template
T& addComponent(Object o, Args&&... args) {
return registry.emplace(o.entity_id, std::forward(args)...);
}

// Function to get a component
template
T* getComponent(Object o) {
return registry.try_get(o.entity_id);
}

// Function to remove a component
template
void removeComponent(Object o) {
ObjectManager::Instance().registry.remove(o.entity_id);
}

private:
ObjectManager() = default;
~ObjectManager() = default;

friend class Object;

Object getObjectFromEntity(entt::entity entity);

std::unordered_map uuidMap; // Map to store UUIDs to objects
std::unordered_map objectName; // Map to store object names
entt::registry registry;
};
< /code>
объект < /p>
#pragma once
#include "entt/entt.hpp"
#include
#include

// Object now serves as an interface to manage entities in EnTT
class Object {
public:
std::string GetName() const;
void SetName(const std::string& name);

// Needed for using Object as a key in std::unordered_map
bool operator==(const Object& other) const {
return entity_id == other.entity_id;
}
private:
Object() = default;
Object(entt::registry& registry);
friend struct std::hash;
friend class ObjectManager; // Needed to delete objects
entt::entity entity_id; // EnTT entity ID
};

// Needed for using Object as a key in std::unordered_map
namespace std {
template
struct hash {
std::size_t operator()(const Object& k) const {
return static_cast(k.entity_id);
}
};
}
< /code>
scenemanager (может заменить при необходимости) < /p>
// Temporary model and texture, will be replaced when we have a proper asset system
const std::string MODEL_PATH = "viking_room.obj";
const std::string TEXTURE_PATH = "viking_room.png";

const std::string LAPTOP = "Laptop_High-Polay_HP_BI_2_obj.obj";

SceneManager& SceneManager::Instance() {
static SceneManager instance;
return instance;
}

void SceneManager::LoadScene() {
// Load the scene
UUID mesh = AssetManager::Instance().loadModel(MODEL_PATH);
UUID texture = AssetManager::Instance().loadTexture(TEXTURE_PATH);

// Create a new object
Object obj = ObjectManager::Instance().createObject("Object");

MeshComponent& m = ObjectManager::Instance().addComponent(obj);
m.uuid = mesh;
m.TextureUUID = texture;

// Add transform component to allow manipulation of the object in the scene
ObjectManager::Instance().addComponent(obj);

Object obj2 = ObjectManager::Instance().createObject("Object2");
UUID mesh2 = AssetManager::Instance().loadModel(LAPTOP);

Transform& t2 = ObjectManager::Instance().addComponent(obj2);
MeshComponent& m2 = ObjectManager::Instance().addComponent(obj2);
m2.uuid = mesh2;

// Stress test
for (int i = 0; i < 10000; i++) {
Object objM = ObjectManager::Instance().createObject("ObjectM");

Transform& t3 = ObjectManager::Instance().addComponent(objM);
// Randomise the transform
t3.position = { (float)(rand() % 20) - 10, (float)(rand() % 20) - 10, (float)(rand() % 20) - 10 };
t3.scale = { 0.1f, 0.1f, 0.1f };

MeshComponent& m3 = ObjectManager::Instance().addComponent(objM);
m3.uuid = mesh2;
}
}


Подробнее здесь: https://stackoverflow.com/questions/794 ... ore-memory
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Вулкан продолжает потреблять все больше и больше памяти
    Anonymous » » в форуме C++
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous
  • Почему подписчик субъекта продолжает потреблять ошибку после первого () оператора (), если следующее излучение этого суб
    Anonymous » » в форуме Javascript
    0 Ответы
    3 Просмотры
    Последнее сообщение Anonymous
  • Сколько памяти может потреблять std::vector при расширении?
    Anonymous » » в форуме C++
    0 Ответы
    11 Просмотры
    Последнее сообщение Anonymous
  • Как использовать вулкан с imgui?
    Anonymous » » в форуме C++
    0 Ответы
    20 Просмотры
    Последнее сообщение Anonymous
  • Как использовать вулкан с imgui?
    Anonymous » » в форуме C++
    0 Ответы
    14 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C++»