Subversion Repositories ps3ware

Rev

Rev 210 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
204 ironpeter 1
/*
2
 * PS3 GPU blitting test program
3
 *
4
 * Copyright 2007 Vivien Chappelier <vivien.chappelier@free.fr>
5
 * Copyright 2007 Peter Popov <IronSPeter@gmail.com>
6
 *
7
 */
8
#include <stdlib.h>
9
#include <stdio.h>
10
#include <stdint.h>
11
#include <unistd.h>
12
#include <string.h>
13
#include <sys/mman.h>
14
#include <sys/ioctl.h>
15
#include <sys/stat.h>
16
#include <signal.h>
17
#include <fcntl.h>
18
#include <math.h>
19
#include <time.h>
20
#include <assert.h>
21
#include <libspe.h>
22
 
23
 
24
extern "C"
25
{
26
#include "../../include/matrix.h"
27
#include "../../src/types.h"
28
#include "../../include/nouveau_class.h"
29
#include "../../src/fifo/utils.h"
30
#include "../../src/fifo/dma.h"
31
#include "../../src/textures/textures.h"
32
#include "../../src/geometry/geometry.h"
33
#include "../../src/geometry/model.h"
34
#include "../../src/shaders/vertex.h"
35
#include "../../src/rop/rop.h"
36
#include "../../src/shaders/fragment.h"
37
};
38
 
39
#include "structs.h"
40
 
41
#define Nv3D 7
42
 
43
 
44
uint32_t width;
45
uint32_t height;
46
uint32_t pitch;
47
 
48
#define  BB 64
49
 
50
 
51
int set_mvp(  uint32_t *fifo, float angle )
52
{
53
 
54
        float matrix[16];
55
 
56
        identity( matrix );
57
        float w = 0.4f;
58
        float h = 0.3f;
59
 
60
        frustrum( -w, +w, -h, +h, 1.0f, 100.0f, matrix );
210 ironpeter 61
        translatef( 0.0f, 0.0f, -4.0f, matrix );
204 ironpeter 62
 
63
        rotatef( angle, 0.0f, 1.0f, 0.0f, matrix );
64
        rotatef( 90.0f, 1.0f, 0.0f, 0.0f, matrix );
65
 
66
        return set_vertex_shader_constants( matrix, 0, 16, fifo, Nv3D );
67
 
68
}
69
 
70
 
71
int set_cnst(  uint32_t *fifo )
72
{
73
 
74
        float coeff[8] = { 1.0f / 4096.0f, 1.0f / 4096.0f, 0.0f, 1.0f  };
75
        return set_vertex_shader_constants( coeff, 4, 4, fifo, Nv3D );
76
 
77
}
78
 
79
void  *map_file( const char *file, int *fd, int *size )
80
{
81
        *size = 0;
82
        *fd = open( file, O_RDONLY );
83
        if( (*fd) != -1 )
84
        {
85
                int status;
86
                struct stat buffer;
87
                status = fstat( *fd, &buffer );
88
                *size = buffer.st_size;
89
                printf( "mmaped %10d bytes from %s \n", (uint32_t)buffer.st_size, file );
90
                return mmap( 0, buffer.st_size, PROT_READ, MAP_PRIVATE, *fd, 0 );
91
        }
92
        return 0;
93
 
94
}
95
 
96
void  unmap_file( void *data, int fd, int size )
97
{
98
 
99
        if( data != 0 )
100
        {
101
                munmap( data, size );
102
        }
103
        if( fd != -1 )
104
        {
105
                close( fd );
106
        }
107
}
108
 
109
 
110
template<class T> struct file_map
111
{
112
 
113
    int fd;
114
    int size;
115
    void *data;
116
public:
117
    int get_size() const
118
    {
119
        return size;
120
    }
121
    T *get_object() const
122
    {
123
        return (T *)data;
124
    }
125
    file_map( const char *file )
126
    {
127
        data = map_file( file, &fd, &size );
128
    }
129
 
130
    ~file_map()
131
    {
132
        unmap_file( data, fd, size );
133
    }
134
 
135
};
136
 
137
 
138
class  memory_pool
139
{
140
    uint8 *data;
141
    size_t ptr;
142
    size_t size;
143
    size_t align;
144
public:
145
    size_t get_offset() const
146
    {
147
        return ptr;
148
    }
149
    memory_pool sub_pool( size_t _size, size_t _align )
150
    {
151
        memory_pool pool = *this;
152
        pool.size = pool.ptr + size;
153
        pool.align = _align;
154
        alloc( _size );
155
        return pool;
156
    }
157
    memory_pool() : data( 0 ), ptr( 0 ), size( 0 ), align( 0 ){};
158
    memory_pool( uint8 *_data, size_t _size, size_t _align ) : data( _data ), ptr( 0 ), size( _size ), align( _align ) {};
159
    void  *alloc( size_t _size )
160
    {
161
        size_t off = _size & ( align - 1 );
162
        if( off )
163
        {
164
            _size += align - off;
165
        }
166
        assert( ptr + _size < size );
167
        void *result = data + ptr;
168
        ptr += _size;
169
        return result;
170
    }
171
};
172
 
173
 
174
class gpu_ring
175
{
176
protected:
177
    size_t *fifo;
178
    size_t  cmd_size;
179
 
180
public:
181
    gpu_ring() : fifo( 0 ), cmd_size( 0 ){};
182
 
183
    size_t set( uint32_t *_fifo )
184
    {
185
        memcpy( _fifo, fifo, cmd_size * 4 );  
186
        return cmd_size;
187
    }
188
 
189
};
190
 
191
class vertex_shader_t : public gpu_ring
192
{
193
 
194
public:
195
 
196
    bool init( const char *file, memory_pool &xdr_pool )
197
    {
198
        file_map<vertex_shader_desc_t> f( file );
199
        if( vertex_shader_desc_t *desc = f.get_object() )
200
        {
201
            fifo = (size_t *)xdr_pool.alloc( 0 );
202
            cmd_size = set_vertex_shader( desc, &desc->aux[1], fifo, Nv3D );
203
            xdr_pool.alloc( cmd_size * 4 );
204
            return true;
205
        }
206
 
207
        return false;
208
 
209
    }
210
};
211
 
212
class pixel_shader_t : public gpu_ring
213
{
214
 
215
public:
216
 
217
    bool init( const char *file, memory_pool &xdr_pool, memory_pool &ddr_pool )
218
    {
219
        file_map<fragment_shader_desc_t> f( file );
220
        if( fragment_shader_desc_t *desc = f.get_object() )
221
        {
222
            size_t off = ddr_pool.get_offset();
223
            size_t length = desc->dword_length * 4;
224
            memcpy( ddr_pool.alloc( 0 ), &desc->aux[1], length );
225
            ddr_pool.alloc( length );
226
            fifo = (size_t *)xdr_pool.alloc( 0 );
227
            cmd_size = set_fragment_shader( desc, off, fifo, Nv3D );
228
            xdr_pool.alloc( cmd_size * 4 );
229
            return true;
230
        }
231
 
232
        return false;
233
 
234
    }
235
};
236
 
237
class texture_t : public gpu_ring
238
{
239
 
240
public:
241
 
242
    bool init( const char *file, memory_pool &xdr_pool, memory_pool &ddr_pool )
243
    {
244
        file_map<texture_desc_t> f( file );
245
        if( texture_desc_t *desc = f.get_object() )
246
        {
247
            size_t off = ddr_pool.get_offset();
248
            size_t length = desc->length;
249
            memcpy( ddr_pool.alloc( length ), sizeof( *desc ) + (uint8_t *)desc, desc->length );
250
            fifo = (size_t *)xdr_pool.alloc( 0 );
251
            cmd_size  = set_texture_2D( desc, off, 0, REPEAT, LINEAR, LINEAR_MIPMAP_LINEAR, fifo, Nv3D );      
252
            xdr_pool.alloc( cmd_size * 4 );
253
            return true;
254
        }
255
 
256
        return false;
257
 
258
    }
259
};
260
 
261
 
262
class raw_data_t
263
{
264
    size_t offset;
265
    size_t size;
266
    void   *data;
267
public:
268
 
269
    void *get_data() const
270
    {
271
        return data;
272
    }
273
    size_t get_offset() const
274
    {
275
        return offset;
276
    }
277
    size_t get_size() const
278
    {
279
        return size;
280
    }
281
    raw_data_t() : offset( 0 ){};
282
 
283
    bool init( const char *file, memory_pool &pool )
284
    {
285
        file_map<uint8_t> f( file );
286
        if( uint8_t *desc = f.get_object() )
287
        {
288
 
289
            offset = pool.get_offset();
290
            size_t length = f.get_size();
291
            memcpy( data = pool.alloc( length ), desc, length );
292
            size = length;
293
            return true;
294
        }
295
 
296
        return false;
297
 
298
    }
299
};
300
 
301
class geometry_t : public gpu_ring
302
{
303
public:    
304
    bool init( const char *file, memory_pool &xdr_pool, size_t vb_offset, size_t ib_offset )
305
    {
306
        file_map<model_desc_t> f( file );
307
        if( model_desc_t *desc = f.get_object() )
308
        {
309
            uint32_t *ptr = (uint32_t *)xdr_pool.alloc( 0 );
310
            fifo = ptr;
311
            ptr += blend_enable( 0, ptr, Nv3D );
312
            ptr += depth_enable( 1, 1, ptr, Nv3D );
313
            ptr += set_geometry_source( &desc->position, DDR, vb_offset, ptr, Nv3D );
314
            ptr += set_geometry_source( &desc->texcoord, DDR, vb_offset, ptr, Nv3D );
315
            ptr += set_index_source( DDR, ib_offset, ptr, Nv3D );
316
            ptr += draw_primitives( 1, TRIANGLES, 0, desc->indices_num, ptr, Nv3D );
317
 
318
            cmd_size = ptr - fifo;
319
            xdr_pool.alloc( cmd_size * 4 );
320
            return true;
321
        }
322
        return false;
323
 
324
    }
325
 
326
};
327
 
328
 
329
class quad_geometry_t : public gpu_ring
330
{
331
public:    
332
    bool init( memory_pool &xdr_pool, size_t vb_offset )
333
    {
334
        uint32_t *ptr = (uint32_t *)xdr_pool.alloc( 0 );
335
        fifo = ptr;
336
 
337
        geom_desc_t pos, tx0, col;
338
 
339
        pos.stride = 24;
340
        pos.components = 3;
341
        pos.format = FLOAT;
342
        pos.type = POS0;
343
        pos.offset = 0;
344
 
345
        col.stride = 24;
346
        col.components = 4;
347
        col.format = HALF;
348
        col.type = COL0;
349
        col.offset = 16;
350
 
351
        tx0.stride = 24;
352
        tx0.components = 2;
353
        tx0.format = HALF;
354
        tx0.type = TEX0;
355
        tx0.offset = 12;
356
 
357
        ptr += blend_enable( 1, ptr, Nv3D );
358
 
359
        blend_desc_t blend;
360
        blend.src_color_blend = ONE;
361
        blend.src_alpha_blend = ONE;
362
        blend.dst_color_blend = ONE;
363
        blend.dst_alpha_blend = ONE;
364
 
365
 
366
        ptr += set_blend_mode( &blend, ptr, Nv3D );    
367
        ptr += depth_enable( 0, 1, ptr, Nv3D );
368
        ptr += set_geometry_source( &pos, DDR, vb_offset, ptr, Nv3D );
369
        ptr += set_geometry_source( &col, DDR, vb_offset, ptr, Nv3D );
370
        ptr += set_geometry_source( &tx0, DDR, vb_offset, ptr, Nv3D );
371
 
372
        cmd_size = ptr - fifo;
373
        xdr_pool.alloc( cmd_size * 4 );
374
        return true;
375
 
376
    }
377
};
378
 
379
vertex_shader_t mvp;
380
pixel_shader_t custom;
381
texture_t troll_texture;
382
texture_t particle_texture;
383
 
384
geometry_t troll;
385
quad_geometry_t particles;
386
 
387
 
388
 
389
int setup_surfaces_with_offset( uint32_t *fifo, int off )
390
{
391
        uint32_t *ptr = fifo;
392
        setup_buffer_t setup;
393
        setup.pitchDepth = pitch;
394
        setup.pitchColor = pitch;
395
        setup.offsetDepth = width * height * 4 * 3;
396
        setup.offsetColor = width * height * 4 * off;
397
        setup.typeDepth = Z16;
398
        setup.width = width;
399
        setup.height = height;
400
 
401
 
402
        ptr += setup_buffers( &setup, ptr, Nv3D );
403
        return ptr - fifo;
404
}
405
 
406
 
407
uint8 data[1024 * 1024] __attribute__((aligned( 128 ) ));
408
memory_pool xdr_pool( data, sizeof( data ), 128 );
409
memory_pool fp_pool;
410
memory_pool tx_pool;
411
memory_pool vr_pool;
412
raw_data_t fx;
413
raw_data_t atlas;
414
void *dynamic;
415
 
416
int bind3d( uint32_t *fifo, uint32_t *fbmem, uint8_t *xdrmem, uint32_t obj, uint32_t jmp )
417
{
418
 
419
        uint32_t *ptr = fifo;
420
        xdrmem = xdrmem;
421
        mvp.init( "../../data/particle.vertex", xdr_pool );
422
        memory_pool gfx_pool( (uint8_t *)fbmem, 252 * 1024 * 1024, 1024 * 1024 );
423
        gfx_pool.alloc( 1024 * 1024 * 32 );
424
        fp_pool = gfx_pool.sub_pool( 1024 * 1024, 128 );
425
        custom.init( "../../data/particle.pixel", xdr_pool, fp_pool );
426
        tx_pool = gfx_pool.sub_pool( 1024 * 1024, 1024 );
427
        troll_texture.init( "../../data/troll.dxt3",  xdr_pool, tx_pool );
428
        particle_texture.init( "../../data/spell.dxt3",  xdr_pool, tx_pool );
429
 
430
        vr_pool = gfx_pool.sub_pool( 1024 * 1024 * 16, 1024 );
431
 
432
        raw_data_t vb;
433
        raw_data_t ib;
434
 
435
        vb.init( "../../data/troll.0.vb", vr_pool );
436
        ib.init( "../../data/troll.0.ib", vr_pool );   
437
        troll.init( "../../data/troll.0.model", xdr_pool, vb.get_offset(), ib.get_offset() );
438
 
439
 
440
 
441
        fx.init( "../../data/spell", xdr_pool );
442
        atlas.init( "../../data/spell.dxt3.atlas", xdr_pool );
443
        particles.init( xdr_pool, vr_pool.get_offset() );
444
 
445
        dynamic = vr_pool.alloc( 1024 * 1024 );
446
 
447
 
448
        ptr += setup_and_voodoo( 0x66604200, 0xfeed0000, obj, ptr, Nv3D );
449
        ptr += setup_surfaces_with_offset( ptr, 1 );
450
        ptr += troll_texture.set( ptr );
451
        ptr += mvp.set( ptr );
452
        ptr += set_mvp( ptr, 180.0f );
453
        ptr += set_cnst( ptr );
454
        ptr += custom.set( ptr );
455
        ptr += set_geometry_pipe( 0xfeed0000, 0xfeed0001, ptr, Nv3D );
456
        ptr += troll.set( ptr );
457
        ptr += jump_to_address( ptr, jmp );    
458
 
459
        return ptr - fifo;
460
}
461
 
462
 
463
 
464
extern spe_program_handle_t spu_handle;
465
 
466
struct job_t
467
{
468
        speid_t spe_id;
469
        program_data_t pd __attribute__((aligned(128)));
470
        job_t() : spe_id( 0 ){};
471
 
472
        void kick_job( )
473
        {
474
 
475
                if( spe_id == 0 )
476
                {
477
                        spe_id = spe_create_thread( 0, &spu_handle, &pd, NULL, -1, 0 );
478
                }
479
 
480
 
481
                while( spe_stat_in_mbox(spe_id) == 0 );
482
                spe_write_in_mbox( spe_id, 1 );
483
        }
484
 
485
        void join()
486
        {
487
                while( spe_read_out_mbox( spe_id ) == (unsigned int)-1 );
488
        }
489
 
490
};
491
 
210 ironpeter 492
#define INUMBER 32
204 ironpeter 493
instance_data_t    insts[INUMBER]  __attribute__((aligned( 128 ) ));
494
uint32_t           dt[INUMBER];
209 ironpeter 495
float              rnds[INUMBER][4];
204 ironpeter 496
 
497
 
498
float rnd( float beg, float end )
499
{
500
    return ( rand() / (float) RAND_MAX ) * ( end - beg ) + beg;
501
}
502
 
503
int gfx_step(  uint32_t *fifo,  uint32_t jmp, int off )
504
{
505
 
506
        static bool init_particles = false;
507
 
508
        if( !init_particles )
509
        {
510
            init_particles = true;
511
 
512
            for( size_t i = 0; i < INUMBER; ++i )
513
            {
514
                dt[i] = ( rand() & 63 ) + 32;
515
                rnds[i][0] = 360.0f * i / (float)( INUMBER );//rnd( 0.0f, 360.0f );
209 ironpeter 516
                rnds[i][1] = rnd( -0.2f, +0.2f );
517
                rnds[i][2] = rnd( -0.8f, +0.3f );
210 ironpeter 518
                rnds[i][3] = rnd( 0.3f, 1.0f );
204 ironpeter 519
 
209 ironpeter 520
 
204 ironpeter 521
                insts[i].time   = rand();
522
                insts[i].col[0] = rnd( 0.8f, 1.0f );
523
                insts[i].col[1] = rnd( 0.8f, 1.0f );
524
                insts[i].col[2] = rnd( 0.8f, 1.0f );
525
                insts[i].col[3] = 1.0f;                        
526
            }
527
        }
528
 
529
 
530
        for( size_t i = 0; i < INUMBER; ++i )
531
        {
532
            insts[i].time += dt[i];
533
            identity( insts[i].mat );
534
 
535
            rotatef( 80.0f, 1.0f, 0.0f, 0.0f, insts[i].mat );
536
            rotatef( off * 0.5f + rnds[i][0], 0.0f, 0.0f, 1.0f, insts[i].mat );
210 ironpeter 537
            translatef( 1.6f, rnds[i][1], rnds[i][2], insts[i].mat );
538
            scalef( rnds[i][3], insts[i].mat );
204 ironpeter 539
 
540
            float d = insts[i].mat[11];
541
 
212 ironpeter 542
            d = ( 1.0f - 0.6f * d );
210 ironpeter 543
            insts[i].scale = rnds[i][3];
204 ironpeter 544
            insts[i].col[0] = d;
545
            insts[i].col[1] = 0.5f + d;
546
            insts[i].col[2] = d;
547
 
548
            //translatef( 1.0f * sin( t * rnds[i][0] ), 1.0f * cos( t * rnds[i][0] ), 1.0f * sin( t * rnds[i][2] ), insts[i].mat );
549
        }
550
 
551
 
552
 
553
        clear_buffer_t clear;
554
        clear.clearR = clear.clearG = clear.clearB = clear.clearA = clear.clearD = 1;
555
        clear.rgba = 50 + ( 10 << 8 ) + ( 5 << 16 );
556
        clear.depth = 0xffff;
557
 
558
        static job_t job;
559
 
560
        static size_t curr = 0x0;
561
 
562
        job.pd.insts = (uint32_t)insts;
563
        job.pd.isize = INUMBER;
564
        job.pd.dynamic = (uint32_t)( dynamic ) + curr * 24;
565
        job.pd.fx = (uint32_t)fx.get_data();
566
        job.pd.atlas = (uint32_t)atlas.get_data();
567
        job.pd.asize = atlas.get_size();
568
        job.kick_job( );
569
        job.join();
570
 
571
 
572
        uint32_t *ptr = fifo;
573
        static float angle = 180.0f;
574
        ptr += setup_surfaces_with_offset( ptr, off % 3 );
575
        ptr += clear_buffers( &clear, ptr, Nv3D );
576
 
577
        ptr += set_mvp( ptr, angle );
578
        ptr += set_cnst( ptr );
579
        //ptr += troll_texture.set( ptr );
580
        //ptr += troll.set( ptr );
581
 
582
        //ptr += custom.set( ptr );
583
        ptr += particles.set( ptr );
584
        ptr += particle_texture.set( ptr );
585
 
586
        ptr += draw_primitives( 0, QUADS, curr, job.pd.quads * 4, ptr, Nv3D );
587
 
588
        curr += job.pd.quads * 4;// + 128;
589
        curr = ( curr + 16 ) & 2047;
590
 
591
        //printf( "%d \n", job.pd.quads );
592
        ptr += jump_to_address( ptr, jmp );
593
        return ptr - fifo;
594
}
595
 
596
 
597
static volatile int cnt;
598
 
599
void wait( volatile uint32_t *volatile ctrl, uint32_t jmp )
600
{
601
        ctrl[0x10] = jmp;
602
        while( ctrl[0x11] != jmp  )
603
        {
604
            ++cnt;
605
        }
606
 
607
}
608
 
609
 
610
static void gfx_test(struct gpu *gpu, unsigned int obj )
611
{
612
        uint32_t *fifo = (uint32_t *)gpu->fifo.virt;
613
        uint32_t *ctrl = (uint32_t *)gpu->ctrl.virt;
614
        uint32_t *vram = (uint32_t *)gpu->vram.virt;
615
        uint8_t *xram = (uint8_t *)gpu->xram.virt;
616
        uint32_t i;
617
 
618
        memset( fifo, 0, gpu->fifo.len );
619
        int wptr;
620
        int ret;
621
        uint32 jmp = ctrl[0x10] & ~(gpu->fifo.len - 1 );
622
 
623
        wptr = (ctrl[0x10] & (gpu->fifo.len - 1)) / 4;
624
 
625
        printf( "%x %x %x\n", wptr, ctrl[0x10], gpu->xram.len );
626
 
627
        ret = bind3d( &fifo[wptr], vram, xram, obj, jmp );
628
 
629
        wait( ctrl, jmp );
630
 
631
        uint32 old_jump = jmp;
632
 
633
        for( i = 0; i < 2000; ++i )
634
        {
635
 
636
            //printf( "asd \n" );
637
            memset( fifo, 0, gpu->fifo.len );
638
 
639
            uint32_t jmpt = jmp + 4 + 4 * ( i & 1 );
640
            fifo[ ( old_jump - jmp ) / 4 ] = 0x20000000 | ( jmp + 0x10 );
641
            old_jump = jmpt;
642
            gfx_step( &fifo[0x10], jmpt, i );
643
            wait( ctrl, jmpt );
644
            flip_scrn( gpu, ( ( i + 2 ) % 3 ) * width * height * 4 );
645
            sync_gpu( gpu );
646
            //flip_scrn( gpu, ( ( i + 1 ) & 1 ) * width * height * 4 );
647
 
648
        }
649
        printf( "done...\n" );
650
 
651
}
652
 
653
struct gpu gpu;
654
 
655
void sigint_handler(int sig)
656
{
657
        (void) sig;
658
        gpu_cleanup(&gpu);
659
}
660
 
661
 
662
 
663
int main(void)
664
{
665
 
666
        if (gpu_init(&gpu) < 0)
667
        {
668
                fprintf(stderr, "Failed to initialize GPU\n");
669
                return -1;
670
        }
671
 
672
        width = gpu.res.xres;
673
        height = gpu.res.yres;
674
        pitch = width * 4;
675
        signal(SIGINT, sigint_handler);
676
 
677
        gfx_test( &gpu, 0xfeed0007 );
678
 
679
        //sleep( 3 );
680
 
681
        gpu_cleanup(&gpu);
682
 
683
        return 0;
684
}