Jump to content

Recommended Posts

Posted

Hi, 
when I create a reasonable amount of decals (~500), the process memory shoots through the roof. 
The ram usage exceeds 40 GB, this makes windows offload some ram onto the SSD, increasing map loading time by a lot.
In this screenshot, I have only instantiated about 500 decals (total of 1000 nodes , of which every second is a decal).
image.thumb.png.a065d074a9498656ba52e1a36a3215de.png

I would like to make this a somewhat production ready system even in the early stage, but I haven't handled many instantiated entities within leadwerks in the past.
This is how I instantiate the decals:

 

auto road = road_decal->Instantiate(world, false, false);

//road->SetScale(1, 1, 1);
road->SetRotation(0.0f, yawDegrees, 0.0f);

road->SetPosition(
    midpoint.x,
    terrainY + 0.02f,
    midpoint.z
);

road->SetScale(length*3, roadHeight, roadWidth);
road->SetMaterial(road_material);
road->SetNavObstacle(false);

roadEntities.push_back(road);

and somewhere before that :
 

...
road_material = LoadMaterial("Materials/road_decal.mat");
road_decal = ::Leadwerks::CreateDecal(
    world
)->As<Entity>();
...

The navmesh is built before the instantiation of the roads.


TLDR;
Instantiating many decals takes up a lot of RAM, and I think it is not supposed to be like that, and I think I am doing something wrong and need help.

Posted
std::vector<shared_ptr<Entity>> roadEntities;
...
                        // Setup once
                    auto road_material = LoadMaterial("Materials/road_decal.mat");
                    auto road_decal = ::Leadwerks::CreateDecal(Game::world)->As<Entity>();
                    road_decal->SetMaterial(road_material);

                    //roadEntities.reserve(500);

                    // Instantiate 500 decals
                    for (int i = 0; i < 500; ++i) {
                        // Replace these with your actual per-decal values
                        float yawDegrees = 0.0f;           // or compute per iteration
                        Vec3 midpoint = { float(i)*2, 0.0f, 0.0f }; // or compute per iteration
                        float terrainY = 0;              // or compute per iteration
                        float length = 100;                // or compute per iteration
                        float roadHeight = 10;            // or compute per iteration
                        float roadWidth = 100.0f;             // or compute per iteration

                        auto road = road_decal->Instantiate(Game::world, false, false);
                        road->SetRotation(0.0f, yawDegrees, 0.0f);
                        road->SetPosition(midpoint.x, terrainY + 0.02f, midpoint.z);
                        road->SetScale(length * 3, roadHeight, roadWidth);
                        road->SetMaterial(road_material);
                        road->SetNavObstacle(false);

                        roadEntities.push_back(road);
                        Print("ok");
                    }

Update, I couldnt replicate it with this, it showed that 500 decals seem to work very well actually

Posted
15 hours ago, Slastraf said:
std::vector<shared_ptr<Entity>> roadEntities;
...
                        // Setup once
                    auto road_material = LoadMaterial("Materials/road_decal.mat");
                    auto road_decal = ::Leadwerks::CreateDecal(Game::world)->As<Entity>();
                    road_decal->SetMaterial(road_material);

                    //roadEntities.reserve(500);

                    // Instantiate 500 decals
                    for (int i = 0; i < 500; ++i) {
                        // Replace these with your actual per-decal values
                        float yawDegrees = 0.0f;           // or compute per iteration
                        Vec3 midpoint = { float(i)*2, 0.0f, 0.0f }; // or compute per iteration
                        float terrainY = 0;              // or compute per iteration
                        float length = 100;                // or compute per iteration
                        float roadHeight = 10;            // or compute per iteration
                        float roadWidth = 100.0f;             // or compute per iteration

                        auto road = road_decal->Instantiate(Game::world, false, false);
                        road->SetRotation(0.0f, yawDegrees, 0.0f);
                        road->SetPosition(midpoint.x, terrainY + 0.02f, midpoint.z);
                        road->SetScale(length * 3, roadHeight, roadWidth);
                        road->SetMaterial(road_material);
                        road->SetNavObstacle(false);

                        roadEntities.push_back(road);
                        Print("ok");
                    }

Update, I couldnt replicate it with this, it showed that 500 decals seem to work very well actually

 

Another update, the code quoted here is sufficient to reproduce the issue.
Using this code generating number of decals vs Ram usage :
100 | 9.6 GB
200,| 17,8 GB
300 | 26,1 GB

To recap; I would like to build a road system where roads are made up of segments of decals, and I need lots of decals for that. 
The ram issue persists even if the decals have no material. Here is an updated code to test yourself:

 

	std::vector<shared_ptr<Entity>> roadEntities;
...                   
 					auto road_decal = ::Leadwerks::CreateDecal(Game::world)->As<Entity>();
                    //road_decal->SetMaterial(road_material);

                    //roadEntities.reserve(500);

                    // Instantiate 500 decals
                    for (int i = 0; i < 300; ++i) {
                        // Replace these with your actual per-decal values
                        float yawDegrees = 0.0f;           // or compute per iteration
                        Vec3 midpoint = { float(i)*2, 0.0f, 0.0f }; // or compute per iteration
                        float terrainY = 0;              // or compute per iteration
                        float length = 100;                // or compute per iteration
                        float roadHeight = 10;            // or compute per iteration
                        float roadWidth = 100.0f;             // or compute per iteration

                        auto road = road_decal->Instantiate(Game::world, false, false);
                        road->SetRotation(0.0f, yawDegrees, 0.0f);
                        road->SetPosition(midpoint.x, terrainY + 0.02f, midpoint.z);
                        road->SetScale(length * 3, roadHeight, roadWidth);
                        //road->SetMaterial(road_material);
                        road->SetNavObstacle(false);

                        roadEntities.push_back(road);
                    }

 

Posted

I have an update on the ram issue, The issue is fixed in the test code by prior reserving elements in the vector.
 

    std::vector<shared_ptr<Decal>> roadEntities;
    roadEntities.reserve(301);

    // and code as from my previous answer

Here is what AI has to say about it:
 

Quote

Without reserve, your std::vector grows by repeated reallocations as you push_back 501 elements, each time allocating a larger array and moving all existing shared_ptrs, which can cause many short-lived allocations and deallocations that look like “RAM exploding” in profilers or during rapid growth. With reserve(501), the vector allocates enough space once up front, so all 501 push_backs just construct the shared_ptrs in place without further reallocations, eliminating the allocation churn.



However, at my actual code , reserving the exact size of elements needed has so far NOT fixed the issue. 
The only difference in the code is that the roadEntities vector is a member of a class inheriting a component. 

Here is the screenshot for proof. I will provide my code afterwards:
image.thumb.png.6d996ffb68a1826d8c06370145ffca1b.png

Here is the code

 

#pragma once
#include "Leadwerks.h"
#include "..\BaseComponent.h"
/...
using namespace Leadwerks;
// ----------------------
// Component
// ----------------------
class LeadwerksRoads : public Component
{
//...
private:
    void RenderRoads();
protected:
    std::vector<shared_ptr<Decal>> roadEntities;
};

and
 

void LeadwerksRoads::RenderRoads()
{
    auto world = GetEntity()->GetWorld();

    if (!world)
        return;


    int renderedCount = 0;
    int zeroLengthCount = 0;
    int decals = 0;

    roadEntities.clear();
    roadEntities.reserve(roadGraph.edges.size());

    Print("Reserved capacity: " + std::to_string(roadEntities.capacity()));

    for (const auto& edge : roadGraph.edges)
    {
       

        const float yawDegrees =0;

        ++renderedCount;
        
        float terrainY = 0;

        auto road = ::Leadwerks::CreateDecal(world);
        road->SetRotation(0.0f, yawDegrees, 0.0f);

        road->SetPosition(
            midpoint.x,
            terrainY + 0.02f,
            midpoint.z
        );

        road->SetScale(length*3, roadHeight, roadWidth);
        road->SetMaterial(road_material);
        //road->SetNavObstacle(false);

        roadEntities.push_back(road);
        decals++;
    }

    Print(
        "Rendered " +
        std::to_string(decals)
    );
}

The issue persists. I have not a clue what the compiler does.
When printing "Reserved capacity" , the vector has the exact capacity as expected before the loop.
I have cut some code but this is the one I use and still causes a ram buildup, even when reserving the elements.

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...