Difference between revisions of "Streaming Cost test"

From Second Life Wiki
Jump to navigation Jump to search
 
(10 intermediate revisions by one other user not shown)
Line 12: Line 12:
== Tests ==
== Tests ==


Target viewport streaming cost at 128m, medium detail (currently 2MB)
Target visible triangles from center of region at medium mesh detail (in preferences) is 250 thousand triangles.
<br>
To verify a mesh object's streaming cost is being calculated correctly:
* Open preferences->graphics and click "Reset"
* Ensure that Mesh detail: Objects is set to "Mid"
* Set draw distance to 256m or greater
* Go to a flat, empty region
* Place a copy of the mesh object in a corner of the sim
* Set the mesh physics shape type to "convex hull" and ensure that the prim equivalence cost matches the object's streaming cost (bound by streaming cost, not physics cost)
* Move your avatar to the center of the sim
* If necessary, scale the mesh object up so that it remains visible from the center of the region when placed at a region corner (prevent object from disappearing due to interest list)
* Place copies of the mesh around the region, '''distributing evenly at ground level,''' until the simulator reports the parcel is full
* Stand at the center of the sim, and do a complete 360 degree turn, ensuring every copy of the mesh object is loaded at appropriate LoD.
* Open develop->consoles->scene statistics
* Ensure "Region Object Streaming Cost" is approximately 15000
* Ensure "Visible" entry for "Region Object Triangle Counts" indicates approximately 250 thousand triangles are visible (+/- 80 thousand).
<br>
If visible triangles is too high, the streaming cost is being too forgiving for the mesh object in question.  If it's too low, streaming cost is being too strict.


* "I got this number by flying around some prim heavy builds (the city north of Ahern) with all rendering disabled but prims, view distance set to 128m, and prim detail set to mid, and watching the peak triangle count per frame in the statistic floater. The average was around 75k/triangles per frame with a peak of 150k, so for meshes a good target would be 125k. On MeshHQ 3, after disabling all rendering but prims (meshes fall under the same category as prims in the render pipeline), the peak triangle count per frame was close to 300k/triangles. On that build, there was no LoD enforcement and a ratio of 8KB/prim for mesh costs, so I'm hoping with a ratio of 4KB/prim and strict LoD enforcement, recreating that build within the new criteria will result in under 125k/triangles per frame."
== Helper Script ==


Use this script to automatically fill a region with a particular mesh.  Put the object to test in the rezzer's inventory and rename it to "test_object" then say "streamrez <cost>" where <cost> is the streaming cost of the object.  It helps to make the rezzer a tall post (say a 1x1x10m prim) so you can track its progress from a distance.


== Verify duck.dae cost ==
<lsl>
* Upload model, choose duck.dae
* In the Physics tab of the upload window, choose "Use Level of Detail: Lowest" LOD
* Click Analyze. Click Simplify. Click Upload.
* Rez the duck.
* Resize the duck to 1x1x1m
* Edit the duck and '''Verify''' the resource cost is 3.
* Resize the duck to 10x10x10m
* Edit the duck and '''Verify''' the resource cost is 7.
* Resize the duck to 20x20x20m
* Edit the duck and '''Verify''' the resource cost is 11.
* Resize the duck to 64x64x64m
* Edit the duck and '''Verify''' the resource cost is 24.


move_to(vector target_pos, float tolerance)
{
    vector cur_pos = llGetPos();
   
    while (llVecDist(<cur_pos.x, cur_pos.y, 0.0>, <target_pos.x, target_pos.y, 0.0>) > tolerance)
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POSITION, target_pos]);
        cur_pos = llGetPos();
    } 
}


Streaming Cost = (MAX(256-Dlowest, 1.0)/32 * KBYTES_IN_LOWEST + MAX(Dlowest-Dlow, 1.0)/32 * KBYTES_IN_LOW + MAX(Dlow - Dmid, 1.0)/32 * KBYTES_IN_MID + MAX(Dmid, 1.0)/32 * KBYTES_IN_HIGH) * COST_SCALER
do_stream_rez(float cost)
{
    llSetColor(<1,0,0>, ALL_SIDES);
    integer count = (integer) (15000/cost);
   
    integer side = (integer) llSqrt((float) count);
   
    float pad = 16.0;
    float spacing = (256.0-pad*2.0)/side;
   
    vector start_pos = llGetPos();


<span style="background:#FFFF33">How can I see KBYTES_IN_LOWEST, KBYTES_IN_LOW, KBYTES_IN_MID and KBYTES_IN_HIGH</span>
    float z = start_pos.z;
   
    integer i;
    rotation rot = llGetRot();
   
    for (i = 0; i < side; i++)
    {
        integer j;
        for (j = 0; j < side; j++)
        {
            float x = pad+i*spacing;
            float y = pad+j*spacing;
            if (i%2 == 0)
            {
                y = 256.0-y;
            }
            vector target = <x,y,z>;
       
            move_to(target, 8.0);
       
            llRezObject("test_object", target,
                        <0,0,0>, rot, side);
        }
    }
       
    move_to(<128,128,z>, 0.0);
    llSetColor(<0,1,0>, ALL_SIDES);
}
   
default
{   
    state_entry()
    {
        llSetColor(<1,1,0>, ALL_SIDES);
        llListen(0, "", llGetOwner(), "");
    }
   
    listen(integer channel, string name, key id, string message)
    {
        if (id == llGetOwner())
        {
            list params = llParseString2List(message, [" "], [""]);
            integer count = llGetListLength(params);
            if (count == 2)
            {
                if (llList2String(params, 0) == "streamrez")
                {
                    float cost = llList2Float(params, 1);
                    do_stream_rez(cost);
                }
            }
        }
    }
}
 
</lsl>

Latest revision as of 08:54, 12 July 2011

Test Plan Name:

Streaming Cost test

Sources

https://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost
https://wiki.secondlife.com/wiki/Mesh_Accounting_Test

Purpose

Verify the amount of data streamed to the viewer is within the expected range.

Tests

Target visible triangles from center of region at medium mesh detail (in preferences) is 250 thousand triangles.
To verify a mesh object's streaming cost is being calculated correctly:

  • Open preferences->graphics and click "Reset"
  • Ensure that Mesh detail: Objects is set to "Mid"
  • Set draw distance to 256m or greater
  • Go to a flat, empty region
  • Place a copy of the mesh object in a corner of the sim
  • Set the mesh physics shape type to "convex hull" and ensure that the prim equivalence cost matches the object's streaming cost (bound by streaming cost, not physics cost)
  • Move your avatar to the center of the sim
  • If necessary, scale the mesh object up so that it remains visible from the center of the region when placed at a region corner (prevent object from disappearing due to interest list)
  • Place copies of the mesh around the region, distributing evenly at ground level, until the simulator reports the parcel is full
  • Stand at the center of the sim, and do a complete 360 degree turn, ensuring every copy of the mesh object is loaded at appropriate LoD.
  • Open develop->consoles->scene statistics
  • Ensure "Region Object Streaming Cost" is approximately 15000
  • Ensure "Visible" entry for "Region Object Triangle Counts" indicates approximately 250 thousand triangles are visible (+/- 80 thousand).


If visible triangles is too high, the streaming cost is being too forgiving for the mesh object in question. If it's too low, streaming cost is being too strict.

Helper Script

Use this script to automatically fill a region with a particular mesh. Put the object to test in the rezzer's inventory and rename it to "test_object" then say "streamrez <cost>" where <cost> is the streaming cost of the object. It helps to make the rezzer a tall post (say a 1x1x10m prim) so you can track its progress from a distance.

<lsl>

move_to(vector target_pos, float tolerance) {

   vector cur_pos = llGetPos();
   
   while (llVecDist(<cur_pos.x, cur_pos.y, 0.0>, <target_pos.x, target_pos.y, 0.0>) > tolerance)
   {
       llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POSITION, target_pos]);
       cur_pos = llGetPos();
   }   

}

do_stream_rez(float cost) {

   llSetColor(<1,0,0>, ALL_SIDES);
   integer count = (integer) (15000/cost); 
   
   integer side = (integer) llSqrt((float) count);
   
   float pad = 16.0;
   float spacing = (256.0-pad*2.0)/side;
   
   vector start_pos = llGetPos();
   float z = start_pos.z;
   
   integer i;
   rotation rot = llGetRot();
   
   for (i = 0; i < side; i++)
   {
       integer j;
       for (j = 0; j < side; j++)
       {
           float x = pad+i*spacing;
           float y = pad+j*spacing;
           if (i%2 == 0)
           {
               y = 256.0-y;
           }
           vector target = <x,y,z>;
       
           move_to(target, 8.0);
       
           llRezObject("test_object", target, 
                       <0,0,0>, rot, side);
       }
   }
       
   move_to(<128,128,z>, 0.0);
   llSetColor(<0,1,0>, ALL_SIDES);

}

default {

   state_entry()
   {
       llSetColor(<1,1,0>, ALL_SIDES);
       llListen(0, "", llGetOwner(), "");
   }
   
   listen(integer channel, string name, key id, string message)
   {
       if (id == llGetOwner())
       {
           list params = llParseString2List(message, [" "], [""]);
           integer count = llGetListLength(params);
           if (count == 2)
           {
               if (llList2String(params, 0) == "streamrez")
               {
                   float cost = llList2Float(params, 1);
                   do_stream_rez(cost);
               }
           }
       }
   }

}

</lsl>