В настоящее время я пытаюсь изменить программу 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>
Я где -то испортил? Потому что я не могу выяснить, какая часть моей программы поглощает память.
Подробнее здесь: https://stackoverflow.com/questions/794 ... ore-memory
Вулкан продолжает потреблять все больше и больше памяти ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение