Ignore:
Timestamp:
Aug 3, 2015, 7:07:02 PM (9 years ago)
Author:
guerin
Message:

raycast: initial distributed implementation

The main task runs on processor (0,0,0). It manages game logic and
initialization, and participates in the rendering process.
The render task runs on all other processors. It tries to render a frame
slice when available, which is raycasting + pixel drawing for a pixel
column of the frame.

Location:
soft/giet_vm/applications/raycast
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/applications/raycast/disp.c

    r679 r683  
    66#include <math.h>
    77#include <hard_config.h>
     8#include <user_sqt_lock.h>
    89
    910#define FIELD_OF_VIEW   (70.f * M_PI / 180.f)   // Camera field of view
     
    1415// Globals
    1516
    16 static unsigned char* buf[2];
    17 static void *         sts[2];
    18 static unsigned int   cur_buf;
     17static unsigned char*           buf[2];         // framebuffer
     18static void *                   sts[2];         // for fbf_cma
     19static unsigned int             cur_buf;        // current framebuffer
     20static volatile unsigned int    slice_x;        // slice index (shared)
     21static sqt_lock_t               slice_x_lock;   // slice index lock
     22static volatile unsigned int    slice_cnt;      // slice count (shared)
    1923
    2024// Textures indexed by block number
     
    168172}
    169173
    170 static unsigned char *loadTexture(char *path)
     174static unsigned char *dispLoadTexture(char *path)
    171175{
    172176    int fd;
     
    191195void dispInit()
    192196{
    193     // allocate framebuffer
     197    unsigned int w, h, p;
     198
     199    // Initialize lock
     200    giet_procs_number(&w, &h, &p);
     201    sqt_lock_init(&slice_x_lock, w, h, p);
     202
     203    // Allocate framebuffer
    194204    buf[0] = almalloc(64, FBUF_X_SIZE * FBUF_Y_SIZE);
    195205    buf[1] = almalloc(64, FBUF_X_SIZE * FBUF_Y_SIZE);
     
    197207    sts[1] = almalloc(64, 64);
    198208
    199     // initialize framebuffer
     209    // Initialize framebuffer
    200210    giet_fbf_cma_alloc();
    201211    giet_fbf_cma_init_buf(buf[0], buf[1], sts[0], sts[1]);
    202212    giet_fbf_cma_start(FBUF_X_SIZE * FBUF_Y_SIZE);
    203213
    204     // load textures
    205     g_tex[1] = loadTexture("misc/rock_32.raw");
    206     g_tex[2] = loadTexture("misc/door_32.raw");
    207     g_tex[3] = loadTexture("misc/handle_32.raw");
    208     g_tex[4] = loadTexture("misc/wood_32.raw");
     214    // Load textures
     215    g_tex[1] = dispLoadTexture("misc/rock_32.raw");
     216    g_tex[2] = dispLoadTexture("misc/door_32.raw");
     217    g_tex[3] = dispLoadTexture("misc/handle_32.raw");
     218    g_tex[4] = dispLoadTexture("misc/wood_32.raw");
    209219
    210220    cur_buf = 0;
     221    slice_cnt = 0;
     222    slice_x = FBUF_X_SIZE;
     223}
     224
     225int dispRenderSlice(Game *game)
     226{
     227    unsigned int x;
     228    int type;
     229    float angle, dist, tx;
     230
     231    sqt_lock_acquire(&slice_x_lock);
     232
     233    if (slice_x == FBUF_X_SIZE) {
     234        // No more work to do for this frame
     235        sqt_lock_release(&slice_x_lock);
     236        return 0;
     237    }
     238    else {
     239        // Keep slice coordinate
     240        x = slice_x++;
     241    }
     242
     243    sqt_lock_release(&slice_x_lock);
     244
     245    angle = game->player.dir - FIELD_OF_VIEW / 2.f +
     246            x * FIELD_OF_VIEW / FBUF_X_SIZE;
     247
     248    // Cast a ray to get wall distance
     249    dist = dispRaycast(game, &type, &tx, angle);
     250
     251    // Perspective correction
     252    dist *= cos(game->player.dir - angle);
     253
     254    // Draw ceiling, wall and floor
     255    dispDrawSlice(game, x, FBUF_Y_SIZE / dist, type, tx);
     256
     257    // Signal this slice is done
     258    atomic_increment((unsigned int*)&slice_cnt, 1);
     259
     260    return 1;
    211261}
    212262
     
    214264{
    215265    int start = giet_proctime();
    216     float angle = game->player.dir - FIELD_OF_VIEW / 2.f;
    217 
    218     // Cast a ray for each pixel column and draw a colored wall slice
    219     for (int i = 0; i < FBUF_X_SIZE; i++)
    220     {
    221         float dist;
    222         int type;
    223         float tx;
    224 
    225         // Cast a ray to get wall distance
    226         dist = dispRaycast(game, &type, &tx, angle);
    227 
    228         // Perspective correction
    229         dist *= cos(game->player.dir - angle);
    230 
    231         // Draw ceiling, wall and floor
    232         dispDrawSlice(game, i, FBUF_Y_SIZE / dist, type, tx);
    233 
    234         angle += FIELD_OF_VIEW / FBUF_X_SIZE;
    235     }
    236 
     266
     267    // Start rendering
     268    slice_cnt = 0;
     269    slice_x = 0;
     270
     271    // Render slices
     272    while (dispRenderSlice(game));
     273
     274    // Wait for completion
     275    while (slice_cnt != FBUF_X_SIZE);
     276
     277    // Flip framebuffer
    237278    giet_fbf_cma_display(cur_buf);
    238279    cur_buf = !cur_buf;
    239280    giet_tty_printf("[RAYCAST] flip (took %d cycles)\n", giet_proctime() - start);
    240281}
     282
  • soft/giet_vm/applications/raycast/disp.h

    r673 r683  
    55
    66void dispInit();
     7int dispRenderSlice(Game *game);
    78void dispRender(Game *game);
    89
  • soft/giet_vm/applications/raycast/game.c

    r673 r683  
    8181static void gameOnBlockHit(int type)
    8282{
    83         g_exit = true;
     83    g_exit = true;
    8484}
    8585
     
    197197    }
    198198}
     199
     200Game *gameInstance()
     201{
     202    return &game;
     203}
  • soft/giet_vm/applications/raycast/game.h

    r673 r683  
    3939void gameRun();
    4040void gameTick();
     41Game *gameInstance();
    4142
    4243#endif // __GAME_H
  • soft/giet_vm/applications/raycast/main.c

    r676 r683  
    44#include <malloc.h>
    55
     6static volatile unsigned int    init_sync = 0;
     7
    68// Exported functions
     9
     10__attribute__((constructor)) void render()
     11{
     12    // Wait for main initialization
     13    while (!init_sync);
     14
     15    Game *game = gameInstance();
     16
     17    // Render slices as soon as it's available
     18    while (1) {
     19        dispRenderSlice(game);
     20    }
     21}
    722
    823__attribute__((constructor)) void main()
    924{
    10         giet_tty_alloc(0);
    11         giet_tty_printf("[RAYCAST] entering main()\n");
     25    unsigned int w, h, p;
     26    unsigned int i, j;
    1227
    13         heap_init(0, 0);
    14         dispInit();
     28    giet_tty_alloc(0);
     29    giet_tty_printf("[RAYCAST] entering main()\n");
     30
     31    // Initialize heap for each cluster
     32    giet_procs_number(&w, &h, &p);
     33    for (i = 0; i < w; i++)
     34        for (j = 0; j < h; j++)
     35            heap_init(i, j);
     36
     37    // Initialize game
     38    dispInit();
     39
     40    init_sync = 1;
    1541
    1642    while (1) {
  • soft/giet_vm/applications/raycast/raycast.py

    r679 r683  
    88#   author : Alain Greiner
    99#######################################################################################
    10 #  This file describes the mapping of the single thread "raycast" application
    11 #  on processor[0][0][0] of a multi-clusters, multi-processors architecture.
     10#  This file describes the mapping of the multi-threaded "raycast" application
     11#  on a multi-clusters, multi-processors architecture.
     12#  The mapping of tasks on processors is the following:
     13#    - one "main" task on (0,0,0)
     14#    - one "render" task per processor but (0,0,0)
     15#  The mapping of virtual segments is the following:
     16#    - There is one shared data vseg in cluster[0][0]
     17#    - The code vsegs are replicated on all clusters containing processors.
     18#    - There is one heap vseg per cluster containing processors.
     19#    - The stacks vsegs are distibuted on all clusters containing processors.
     20#  This mapping uses 5 platform parameters, (obtained from the "mapping" argument)
     21#    - x_size    : number of clusters in a row
     22#    - y_size    : number of clusters in a column
     23#    - x_width   : number of bits for x field
     24#    - y_width   : number of bits for y field
     25#    - nprocs    : number of processors per cluster
    1226####################################################################################
    1327
     
    1529def extend( mapping ):
    1630
     31    x_size    = mapping.x_size
     32    y_size    = mapping.y_size
    1733    nprocs    = mapping.nprocs
    18     x_width   = mapping.x_width
    19     y_width   = mapping.y_width
    2034
    2135    # define vsegs base & size
     
    3549    vspace = mapping.addVspace( name = 'raycast', startname = 'raycast_data', active = False )
    3650   
    37     # data vseg
     51    # data vseg : shared / cluster[0][0]
    3852    mapping.addVseg( vspace, 'raycast_data', data_base , data_size,
    3953                     'C_WU', vtype = 'ELF', x = 0, y = 0, pseg = 'RAM',
     
    4155                     local = False )
    4256
    43     # code vseg
    44     mapping.addVseg( vspace, 'raycast_code', code_base , code_size,
    45                      'CXWU', vtype = 'ELF', x = 0, y = 0, pseg = 'RAM',
    46                      binpath = 'bin/raycast/appli.elf',
    47                      local = False )
     57    # code vsegs : local (one copy in each cluster)
     58    for x in xrange (x_size):
     59        for y in xrange (y_size):
     60            cluster_id = (x * y_size) + y
     61            if ( mapping.clusters[cluster_id].procs ):
     62                mapping.addVseg( vspace, 'raycast_code_%d_%d' %(x,y),
     63                                 code_base , code_size,
     64                                 'CXWU', vtype = 'ELF', x = x, y = y, pseg = 'RAM',
     65                                 binpath = 'bin/raycast/appli.elf',
     66                                 local = True )
    4867
    49     # stack vseg             
    50     mapping.addVseg( vspace, 'raycast_stack', stack_base, stack_size,
    51                      'C_WU', vtype = 'BUFFER', x = 0 , y = 0 , pseg = 'RAM',
    52                      local = False, big = True )
     68    # stacks vsegs: local (one stack per processor => nprocs stacks per cluster)
     69    for x in xrange (x_size):
     70        for y in xrange (y_size):
     71            cluster_id = (x * y_size) + y
     72            if ( mapping.clusters[cluster_id].procs ):
     73                for p in xrange( nprocs ):
     74                    proc_id = (((x * y_size) + y) * nprocs) + p
     75                    size    = (stack_size / nprocs) & 0xFFFFF000
     76                    base    = stack_base + (proc_id * size)
     77                    mapping.addVseg( vspace, 'raycast_stack_%d_%d_%d' % (x,y,p),
     78                                     base, size, 'C_WU', vtype = 'BUFFER',
     79                                     x = x , y = y , pseg = 'RAM',
     80                                     local = True, big = True )   
    5381
    54     # heap vseg
    55     mapping.addVseg( vspace, 'raycast_heap', heap_base, heap_size,
    56                      'C_WU', vtype = 'BUFFER', x = 0 , y = 0 , pseg = 'RAM',
    57                      local = False )
     82    # heap vsegs : shared (one per cluster)
     83    for x in xrange (x_size):
     84        for y in xrange (y_size):
     85            cluster_id = (x * y_size) + y
     86            if ( mapping.clusters[cluster_id].procs ):
     87                size  = heap_size
     88                base  = heap_base + (cluster_id * size)
     89                mapping.addVseg( vspace, 'raycast_heap_%d_%d' %(x,y), base , size,
     90                                 'C_WU', vtype = 'HEAP', x = x, y = y, pseg = 'RAM',
     91                                 local = False )
    5892
    59     # task
    60     mapping.addTask( vspace, 'raycast', 0, 0, 0, 0, 'raycast_stack', 'raycast_heap', 0 )
     93    # distributed tasks / one task per processor
     94    for x in xrange (x_size):
     95        for y in xrange (y_size):
     96            cluster_id = (x * y_size) + y
     97            if ( mapping.clusters[cluster_id].procs ):
     98                for p in xrange( nprocs ):
     99                    trdid = (((x * y_size) + y) * nprocs) + p
     100                    if  ( x == 0 and y == 0 and p == 0 ):       # main task
     101                        task_index = 1
     102                        task_name  = 'main_%d_%d_%d' %(x,y,p)
     103                    else:                                       # render task
     104                        task_index = 0
     105                        task_name  = 'render_%d_%d_%d' % (x,y,p)
     106
     107                    mapping.addTask( vspace, task_name, trdid, x, y, p,
     108                                     'raycast_stack_%d_%d_%d' % (x,y,p),
     109                                     'raycast_heap_%d_%d' % (x,y),
     110                                     task_index )
    61111
    62112    # extend mapping name
Note: See TracChangeset for help on using the changeset viewer.