Changes between Initial Version and Version 1 of Loading


Ignore:
Timestamp:
Feb 23, 2008, 4:18:58 AM (16 years ago)
Author:
trac
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Loading

    v1 v1  
     1[KEEP IN SYNC WITH LOADER.H!]
     2
     3Overview
     4--------
     5
     6"Loading" is the act of preparing a game session, including reading all
     7required data from disk. Ideally, this would be very quick, but for complex
     8maps and/or low-end machines, a duration of several seconds can be expected.
     9Having the game freeze that long is unacceptable; instead, we want to display
     10the current progress and task, which greatly increases user patience.
     11
     12
     13Allowing for Display
     14--------------------
     15
     16To display progress, we need to periodically 'interrupt' loading.
     17Threads come to mind, but there is a problem: since OpenGL graphics calls
     18must come from the main thread, loading would have to happen in a
     19background thread. Everything would thus need to be made thread-safe,
     20which is a considerable complication.
     21
     22Therefore, we load from a single thread, and split the operation up into
     23"tasks" (as short as possible). These are typically function calls from the
     24old !InitEverything(); instead of being called directly, they are registered
     25with our queue. We are called from the main loop and process as many tasks
     26as possible within one "timeslice".
     27
     28After that, progress is updated: an estimated duration for each task
     29(derived from timings on one machine) is used to calculate headway.
     30As long as task lengths only differ by a constant factor between machines,
     31this timing is exact; even if not, only smoothness of update suffers.
     32
     33
     34Interrupting Lengthy Tasks
     35--------------------------
     36
     37The above is sufficient for basic needs, but breaks down if tasks are long
     38(> 500ms). To fix this, we will need to modify the tasks themselves:
     39either make them coroutines, i.e. have them return to the main loop and then
     40resume where they left off, or re-enter a limited version of the main loop.
     41The former requires persistent state and careful implementation,
     42but yields significant advantages:
     43 * progress calculation is easy and smooth,
     44 * all services of the main loop (especially input<sup id="fn_1_back">[wiki:#fn_1 1]</sup>) are available, and
     45 * complexity due to reentering the main loop is avoided.
     46
     47We therefore go with the 'coroutine' (more correctly 'generator') approach.
     48Examples of tasks that take so long and typical implementations may
     49be seen in !MapReader.cpp.
     50
     51
     52Intended Use
     53------------
     54
     55Replace the !InitEverything() function with the following:
     56{{{
     57  LDR_BeginRegistering();
     58  LDR_Register(..) for each sub-function<sup id="fn_2_back">[[#fn_2|2]]</sup>
     59  LDR_EndRegistering();
     60}}}
     61Then in the main loop, call LDR_ProgressiveLoad().
     62
     63
     64== Notes ==
     65<cite id="fn_1">[wiki:#fn_1_back Note 1:] </cite> input is important, since we want to be able to abort long loads or even exit the game immediately.
     66
     67<cite id="fn_2">[wiki:#fn_2_back Note 2:] </cite> !RegMemFun from !LoaderThunks.h may be used instead; it takes care of registering member functions, which would otherwise be messy.