Showing posts with label debugging. Show all posts
Showing posts with label debugging. Show all posts

Monday, 24 October 2016

Future City: Update 8 - A Mixed Bag

I haven't managed to write anything this last week (or two) due to other things going on in my life (shock!), and not really feeling like I've been focused on one particular thing.  Instead of a themed post let's just have a look through what's been going on.

Refinement Fixes

Spent some time tidying up the city a bit.  There are a few places where detail refinement was being blocked so I investigated those.
  • Empty Stacker recursion procedure leaf nodes were not ignored.
Stacker Merge appears as leaf when no further content needed, but should be ignored as not a geometry producer itself.
(excuse low-res image, Cairo scaled it down because the GraphViz output was too large)
  • Temporary general triangle fill added for rooftops didn't support refinement.
Roof triangle refinement - before and after
  • Bolts had bounds that were too large, needed to be pre-shrunk.
Bolt bounds blocking refinement - additional re-size in procedure to fix
  • Mesh primitive operators were not being counted as geometry producing (which broke the fix for the Stacker recursion issue above).
Post load checks to classify operators by whether they modify/produce geometry or not.
  • Unnecessary deep refinement of surfaces meant a deluge of synthesis when you strayed very close to a surface. This was slowing things down a little so I added a limit check in the sub-division process.
Adding a refinement limit test, whilst also abstracting out the recursion check to make it more re-usable.
To help track down some of these I added a bit more error diagnostics information:
  • Capture errors show in view panel for selected node
  • Error filter slider for when too many to display at once
  • Any bounds information in the error messages is visualised in red
Additional error diagnostics - better messages, error select, and bounds rendering

More Girders

Couldn't resist more girder improvements as this has become a bit of an 'extreme detail' test case.
  • Washers under nuts
  • Proper facets on bolts
  • Threads on the bolts (hacky, but fine for now)
Washers, faceted nuts, and threads.
  • Added cross bracing to girders
  • Fillet pieces for cross bracing
Cross-bracing and attachment fillets
  • Added rolling fillets to I-beam section
  • Added welds to fillets and fixing plates
Welds and I-beam section forming fillets
All a bit excessive, but some good tests of the detail management refinement systems.  Several issues and bugs were surfaced from this work.

The Wilderness

To make the city more interesting, and provide more of a 'setting' for it I decided to surround it with a Rural district type.  Currently just green/grass, this breaks up the city tone and gives it a rounder appearance.
Rural district type now surrounds the city.
This will provide something to have as the backdrop, or vista, when height support is added and we can have hills and mountains in the background.
This was implemented by re-purposing the commercial district type and giving it a negative gradient along it's radius instead of a positive one like the central districts.  I also parameterised the location, sizes and weights of the district types so we get much greater city layout variance as we vary the city seed values.
Some parameterised city examples

Demo Planning

I'm aiming to have my first-pass city demo-able by the end of the year, and so far I feel like I'm on track for that.  I thought I'd better make a clearer plan though so I spent a morning breaking down the things I have left to do and thinking about the timings.  Here's the to-do list:
  • Finish filling out the placeholder zones (1) - I really need to fill in the residential and leisure areas as they will lend a 'more human' aspect to the city (business and industrial so far).  I'm postponing commercial and spaceport as there are more important things to focus on.
  • Implement first-pass landscape support (1) - A big thing this city doesn't have yet is elevation.  It was always something I wanted to do to add richness and interest to the city.  So we need support for a height function (of some sort), blending (to interface with flat parts), and placing of blocks on landscape (giving them the appropriate elevation).
  • Height integration (1) - Once supported, the natural areas (leisure, surround, and business in-fill) and the interfaces between adjacent elevations need content to provide pleasant and realistic transitions.  This will need to take into account block boundaries, height, and importantly; access ways (or lack thereof) between blocks.
  • Detail pass (2) - Another pass is needed to add more detail to the low-level city, that you will see when 'walking around' at street-level. This includes features like doors, windows, pavement, as well as assets such as bins, streetlights, benches, planters, and maybe trees.
  • Navigation/viewing (1) - To demo this city properly I need people to be able to control the camera in the standalone player.  This would start with basic is keyboard/mouse (FPS) support, with controller support coming later, and then maybe an attract-mode camera mode if there is time.  This would be quite involved as it will need to 'explore' the city to find good camera positions and paths (for some definition of 'good').
  • Lighting (4) - I'd really like to try out my lighting ideas, they should really bring the city alive.  This would also include some fogging/haze/sky work, and maybe some simple clouds for fun.
  • Bonus: Transparency and reflection - If I get time or want a break for something more adventurous I'll try and get some transparency and reflection support in to allow water and glass effects to be added.
Timings (in brackets) are estimated weeks.  We'll see how it goes as I am already a little behind and am still due to have some time off.

Next

I need to get the residential parts populated as soon as I can, so I'll be looking at more 'house-like' buildings and how to create them.

Wednesday, 28 September 2016

Future City: Update 6 - A Balancing Act

Industrial Zone

Using the previous steel structure procedures and some new bits and pieces I've been building a few elements for populating the industrial areas of the city.  For now we have:
  • Warehouse or factory building, with roof-top windows/solar panels, and chimneys.
  • Round storage silo or tank, with and without steel support structure around it.
  • Simple tower based on the steel-work structures.
  • Simple chimney of a couple of different styles.
Structures for first-pass industrial zone
During the creation of these, I've been regularly checking the look of the city.  I was pleased with the initial appearance and the variety and layout was working well giving a good view.
Structures in use throughout the industrial districts.

A Recurring Problem

As more elements and more detail were added, holes in the industrial blocks often appeared.
A hole in the industrial zone
This is an indicator of a procedure synthesis running out of buffer space, due to either too much geometry (triangles/lines) or too much calculation (procedure depth/complexity).  To find the problem procedure a bit of digging using the view diagnostics panel is required thus:
  1. Set render depth to show only the tier with the problem in.
  2. Turn on octree node display.
  3. Set octree node depth to match render depth selected above.
  4. Set the node highlight to the node surrounding the problem area.
First stage of diagnosis; what is the error?
This should show up the actual error message (stat shows first error message under node).  To see exactly what happened during the synthesis of this model we can perform these further steps:
  1. Open the engine dev panel to show the synthesis monitoring panel.
  2. Switch on node model filtering to only render models under this node.
  3. Set the model select to only render the problem model.
  4. Request synth analysis graph generation (triggers re-synth).
Second stage of diagnosis; which exact model?
This will re-synthesise the model (shown in the synth panel) so we can look at the output stats in more detail.
Third stage of diagnosis; what sort of memory did we run out of?
From this we can see that we are running out of parameter buffer (abbreviated to 'Control' here), the memory used for all the information flowing between and through the procedures as the calculations are performed.  This will be because the city block sub-division is quite demanding due to there being quite a depth to the process between the top level of the city at which we are starting and where we actually start to generate geometry.

Turning Up The Heat

Hitting these problems has left me feeling a bit in the dark about how well the system is performing in general, how close we are to having them happen again else-where, and where else we may need to improve the procedures building our scene.  It is a balancing act fitting the design and requirements into the resources available (as is often the case), but this is going to be a common workflow occurrence and we need more tools to help us monitor the situation as we work.
A visualisation tool often used for assessing the overall level of something and getting a good feel of how some value varies across a space is a heat-map.
An example of a heat-map
There are many metrics we could benefit from being able to visualise such as:
  • Rendering cost (triangle count, draw calls, materials)
  • Memory use (system memory, GPU memory, synthesis buffer)
  • Synthesis cost (time/cycles taken, buffer use)
  • Measures of complexity (synth depth, stack use, passes generated, analysis, refinement level)
  • Scene complexity (octree nodes, model counts, mesh counts, node status)
All of these help us assess the overall cost and effectiveness of the procedures creating our world.
Some support work was required to capture the statistics needed from the synthesis process, and propagate it through to the rendering stage (with the meshes). Plus, because the output of synthesis is often merged into single meshes, we also needed a way to render parts of meshes separately to give per-procedure colourising.
Various heat-map modes: Triangles, Cost, Time, Stack, Depth
Each new display mode has its own scale configuration setting so that the range of values being visualised in the scene can be seen in the most detail by spreading them across the full colour gradient.
Gradient scaling settings for each heat-map mode
By also having a distinct colour for a 'maxed-out' value, i.e. on or above the scale setting we can interactively measure the value on a particular element in the scene by dialling the value up and down until we are on the changeover point between being the top end of the gradient and the highlight colour.
I'm not 100% happy with the choice of colour gradient, but full spectrum gradients (which I assumed would be best) seem more suited to continuous functions and not the more random patterns we get here.  Instead I'm trying a simpler black-blue-cyan-white 'icy' gradient, with red for out-of-range values (above the chosen scale setting).

Hot In The City

Testing these display modes out on Future City as a whole shows that we are actually in a pretty good position with fairly low quantities of geometry and no hot-spots that really stand out as problematic.
Triangle counts visualised across detail levels.  Only a few hot-spots at around 7,500 triangles.
It looks like we can actually afford a fair bit more geometry and detail, but at the moment we can't afford synthesis cost (hence the holes).
Typical synth stats for chunk of the city.  Scope for a re-balance I think.
In the upper (distant) tiers most models are in 5,000 to 10,000 triangle range, and the lower tiers are at about 1,500 to 3,000 triangle range, which is pretty low for assets these days, with the overall GPU memory at about 100MB with the viewpoint in the centre of the city.  The draw-calls are moderately high at about 1,000 but this shouldn't change much as more detail is added and can be improved in other ways later on (I'm not doing a frustum cull yet for example!).
So, we need to reduce the synthesis cost.  There are a couple of ways we could go here:
  1. Reduce the complexity of some of the more complex procedures, for example we could convert our super-splitter procedure (see last weeks post [link]) into an operator.
  2. We can re-balance the way each synthesiser's buffer is allocated so there is more parameter space available (and less geometry space).
  3. We can look at one of the several planned optimisation passes on the synthesis processing and evaluation itself.
  4. Other ways?  (there are always other ways).
At the moment I think it is a bit premature to bake the Splitter proc into a procedure as we lose the ability to live edit and continue to improve it (much slower turnaround).  Some investigation of the usage of buffer memory would be helpful in deciding on a new parameter/geometry split for the buffers, perhaps with a buffer use heat-map mode?  I didn't want to get into optimising the synth system yet as I think I can get more elsewhere first and it's tricky work.

Hot-line

I did do some work simplifying the steel tower procedure, which seemed particularly bad, using line primitives (which I have so-far not needed).  In the far distance, the steel beams reduce down to 8 triangles each, but this seemed too much so I added an extra detail switch to a single line segment.  This helped the geometric/visual detail level, but didn't  help the synthesis complexity as we were still having to sub-divide down a lot to get to the individual girders.  Instead of relying on these line based beams I remembered I had a line grid primitive (originally used to draw the ground-plane grid) and so switched this in at a higher level for the steel-work side sections.  Thus each tower is now made of four grid primitives in the distance.  I took this a stage further by double the grid cell size progressively too as I noticed that the fixed width (screen space) line rendering becomes a solid block when the tower is really small.  This helps keep it looking thinned out and again reduces the render cost.
Reduction in tower complexity at lower detail levels by use of line (grid) primitive.

Late Night Ideas

One night last week I couldn't sleep for thinking about these problems and an enticing thought occurred to me about how I can neatly improve this synthesis depth/complexity problem by an order of magnitude and allow lots more detail for the distant city.  This will help a lot for aerial views of the city where you should be able to see a huge amount of small detail when at a considerable distance (probably the worst case scenario).  I think I'm going to explore this next after playing with the synthesis memory balancing.  More details next time… maybe…