Mercurial > hg > Game > Cerium
view Renderer/Engine/viewer.cc @ 1131:220f9032d2d2 draft
RENDERING_TASK was divided into CREATE_PP_TASK and CREATE_SP_TASK.
author | root@dolphins.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Sun, 13 Feb 2011 23:29:11 +0900 |
parents | 5addc6c1d5c4 |
children | f326494ffdc7 |
line wrap: on
line source
#include <SDL.h> #include "viewer.h" #include "viewer_types.h" #include "SceneGraph.h" #include "SceneGraphRoot.h" #include "scene_graph_pack.h" #include "matrix_calc.h" #include "Func.h" #include "error.h" #include "TaskManager.h" #include <wchar.h> #include "Pad.h" #include "Application.h" #include "lindaapi.h" #include "SchedTask.h" /* measure for FPS (Frame Per Second) */ static int start_time; static int this_time; int frames; // static void post2speRunLoop(void *viewer); //static void post2runMove(void *viewer); //static void post2exchange_sgroot(void *viewer); //static void post2speRunLoop(void *viewer); //SceneGraphRootPtr sgroot_2; /* Data Pack sent to Other CPUs (ex. SPE) */ RederingData r[2]; int ppi, spi = 0; /** * */ Viewer::Viewer(TaskManager *m, ViewerDevice *vd, int b, int w, int h, int _num) { spe_num = _num; manager = m; dev = vd; pixels = dev->video_init(manager, b, w, h); width = dev->width; height = dev->height; bpp = dev->bpp; } int Viewer::get_ticks(void) { int time; time = SDL_GetTicks(); return time; } bool Viewer::quit_check(void) { SDL_Event event; while(SDL_PollEvent(&event)) { if (event.type==SDL_QUIT) { return true; } } Uint8 *keys=SDL_GetKeyState(NULL); if (keys[SDLK_q] == SDL_PRESSED) { return true; } return false; } void Viewer::quit(void) { SDL_Quit(); } void Viewer::run_init(TaskManager *manager, Application *app) { this->manager = manager; if (spe_num == 0) spe_num = 1; sgroot = new SceneGraphRoot(this->width, this->height); sgroot->tmanager = manager; int light_num = 4; int size = sizeof(float)*4*light_num; //xyz+alfa(4) * light_num(4) int light_size = size / sizeof(float); light_xyz_stock = (float *)manager->allocate(size); light_xyz = (float *)manager->allocate(size); for (int i = 0; i < light_size ; i++) { light_xyz[i] = 0.0f; } for(int i = 0; i < spe_num; i++) { HTaskPtr data_load = manager->create_task(DataAllocate); data_load->set_param(0,(memaddr)3); // num of allocate block data_load->set_param(1,(memaddr)(sizeof(float)*4*light_num)); // 1st allocate size data_load->set_param(2,(memaddr)Light); // 1st id data_load->set_param(3,(memaddr)(light_num * sizeof(int))); // 2nd size data_load->set_param(4,(memaddr)LightSwitch); // 2nd id data_load->set_param(5,(memaddr)16); // 3rd size data_load->set_param(6,(memaddr)LightSysSwitch); // 3rd id data_load->set_cpu((CPU_TYPE)((int)SPE_0 + i)); data_load->spawn(); } light_switch = (int*)manager->allocate(size); for (int i = 0; i < light_num; i++) { light_switch[i] = 0; } size = 16; // LightSysSwitch は 4byte. 残り 12byte は DMA転送の為のパディング light_sysswitch = (int*)manager->allocate(size); for (unsigned int i = 0; i < size / sizeof(int); i++) { light_sysswitch[i] = 0; } start_time = get_ticks(); this_time = 0; frames = 0; this->app = app; MainLoop *mainloop = app->init(this, this->width, this->height); mainloop->mainLoop(); } HTaskPtr Viewer::initLoop() { HTaskPtr task_next; HTaskPtr task_tex; for(int i=0;i<2;i++) { r[i].ppack = (PolygonPack*)manager->allocate(sizeof(PolygonPack)); r[i].ppack->next = 0; r[i].spackList_length = (this->height + split_screen_h - 1) / split_screen_h; r[i].spackList = (SpanPack*)manager->allocate(sizeof(SpanPack)*r[i].spackList_length); // printf("spackList %0lx height %d\n",(unsigned long)r[i].spackList, this->height); /** * SPU に送る address list は 16 バイト倍数でないといけない。 * spackList_length*sizeof(SpanPack*) が 16 バイト倍数になるような * length_align を求めている。はみ出した部分は使われない * (ex) spackList_length が 13 の場合 * spackList_length_align = 16; * 実際に送るデータは64バイトになるのでOK * 14,15,16 の部分は何も入らない。 */ r[i].spackList_length_align = (r[i].spackList_length + 3)&(~3); /* 各 SPU が持つ、SpanPack の address list */ r[i].spackList_ptr = (SpanPack**)manager->allocate(sizeof(SpanPack*)*r[i].spackList_length_align); for (int j = 0; j < r[i].spackList_length; j++) { r[i].spackList_ptr[j] = &r[i].spackList[j]; } for (int j = 1; j <= r[i].spackList_length; j++) { r[i].spackList[j-1].init(j*split_screen_h); } } task_next = manager->create_task(RUN_LOOP_TASK,0,0,0,0); task_next->set_param(0, (void*)this); // ここは、Iterator を用意するべきだよね for (int j = 0; j < spe_num; j++) { task_tex = manager->create_task(LoadTexture,0,0,0,0); task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + j)); task_next->wait_for(task_tex); task_tex->spawn(); } task_next->spawn(); return 0; } void Viewer::getKey() { Pad *pad = sgroot->getController(); if (pad->right.isHold()) { keyPtr->right = HOLD; } else if (pad->right.isPush()) { keyPtr->right = PUSH; } else { keyPtr->right = NONE; } if (pad->left.isHold()) { keyPtr->left = HOLD; } else if (pad->left.isPush()) { keyPtr->left = PUSH; } else { keyPtr->left = NONE; } if (pad->up.isHold()) { keyPtr->up = HOLD; } else if (pad->up.isPush()) { keyPtr->up = PUSH; } else { keyPtr->up = NONE; } if (pad->down.isHold()) { keyPtr->down = HOLD; } else if (pad->down.isPush()) { keyPtr->down = PUSH; } else { keyPtr->down = NONE; } if (pad->circle.isHold()) { keyPtr->circle = HOLD; } else if (pad->circle.isPush()) { keyPtr->circle = PUSH; } else { keyPtr->circle = NONE; } } void Viewer::mainLoop() { if (pixels) { initLoop(); } else { HTaskPtr task_next = manager->create_task(EXEC_ONLY_TASK, 0, 0, 0, 0); task_next->set_param(0, (void*)this); task_next->spawn(); } } bool Viewer::main_exec(HTaskPtr task_next) { psx_sync_n(); task_next = app->application_task(task_next, this); dev->clear_screen(); bool quit_flg; quit_flg = quit_check(); if (quit_flg == true) { this_time = get_ticks(); run_finish(); return false; } dev->clean_pixels(); pixels = dev->flip_screen(pixels); sgroot->updateControllerState(); if (app->app_loop(this)) { //TaskArray を使うか使わないか if (sgroot->gtask_array != NULL) { sgroot->create_task_array(); sgroot->allExecute(width, height); sgroot->task_array_finish(); } else { sgroot->allExecute(width, height); } } light_xyz_stock = sgroot->getLightVector(); light_switch_stock = sgroot->getLightSwitch(); light_sysswitch_stock = sgroot->getLightSysSwitch(); return true; } void Viewer::run_loop(HTaskPtr task_next) { if (main_exec(task_next)) { //rendering(task_next); task_next->spawn(); } } SchedDefineTask1(EXEC_ONLY_TASK,exec_only_task); static int exec_only_task(SchedTask *smanager, void *rbuf, void *wbuf) { Viewer *viewer = (Viewer*)smanager->get_param(0); HTaskPtr task_next = smanager->create_task(EXEC_ONLY_TASK, 0, 0, 0, 0); task_next->set_param(0, (void*)viewer); if (viewer->main_exec(task_next)) { task_next->spawn(); } return 0; } SchedDefineTask1(RUN_LOOP_TASK,run_loop_task); static int run_loop_task(SchedTask *smanager, void *rbuf, void *wbuf) { Viewer *viewer = (Viewer*)smanager->get_param(0); HTaskPtr task_next = smanager->create_task(CREATE_PP_TASK, 0, 0, 0, 0); task_next->set_param(0, (void*)viewer); viewer->run_loop(task_next); return 0; } void Viewer::run_collision() { } SchedDefineTask1(CREATE_PP_TASK, create_pp_task); static int create_pp_task(SchedTask* smanager, void* rbuf, void* wbuf) { Viewer *viewer = (Viewer*)smanager->get_param(0); HTaskPtr task_next = smanager->create_task(CREATE_SP_TASK, 0, 0, 0, 0); task_next->set_param(0, (void*)viewer); viewer->create_pp(task_next); return 0; } void Viewer::create_pp(HTaskPtr task_next) { rendering_pp(task_next, sgroot); // Barrier 同期 // run_draw() を呼ぶ post2runDraw task_next->spawn(); // create_sp_task } SchedDefineTask1(CREATE_SP_TASK, create_sp_task); static int create_sp_task(SchedTask* smanager, void* rbuf, void* wbuf) { Viewer *viewer = (Viewer*)smanager->get_param(0); HTaskPtr task_next = smanager->create_task(DRAW_TASK, 0, 0, 0, 0); task_next->set_param(0, (void*)viewer); viewer->create_sp(task_next); return 0; } void Viewer::create_sp(HTaskPtr task_next) { rendering_sp(task_next, sgroot); // Barrier 同期 // run_draw() を呼ぶ post2runDraw task_next->spawn(); // draw_task } SchedDefineTask1(DRAW_TASK, draw_task); static int draw_task(SchedTask* smanager, void* rbuf, void* wbuf) { Viewer* viewer = (Viewer*)smanager->get_param(0); HTaskPtr task_next = smanager->create_task(RUN_LOOP_TASK, 0, 0, 0, 0); task_next->set_param(0, (void*)viewer); viewer->run_draw(task_next); return 0; } void Viewer::run_draw(HTaskPtr task_next) // 引数に post2runLoop を入れるようにする { common_draw(task_next); task_next->spawn(); // run_loop_task // TASK_DRAW_SPAN が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ frames++; } /* flag_drawable な Scenegraph の総数を求める */ int sg_drawable_num(SceneGraphPtr scenegraph) { SceneGraphPtr sg = scenegraph; int sg_count = 0; while (sg) { if (sg->flag_drawable) { sg_count++; } if (sg->children != NULL) { sg = sg->children; } else if (sg->brother != NULL) { sg = sg->brother; } else { while (sg) { if (sg->brother != NULL) { sg = sg->brother; break; } else { if (sg->parent == NULL) { sg = NULL; break; } else { sg = sg->parent; } } } } } return sg_count; } void Viewer::rendering_pp(HTaskPtr task_next, SceneGraphRoot *sgroot) { HTaskPtr game_task_array = 0; /* GameTask の処理の終了を待ってからポリゴンを作る */ if (sgroot->gtask_array != NULL) { game_task_array = sgroot->gtask_array->get_task_array(); } PolygonPackPtr out_pp = r[ppi].ppack; SceneGraphPtr t = (SceneGraphPtr)manager->allocate(sizeof(SceneGraph)); //多分このsg_remove_listであってる?。チェック対象かも for (t = sgroot->sg_remove_list; t != NULL; t = t->next) { for (int i = 0; i < t->pp_num; i++) { HTaskPtr create_pp = manager->create_task(CreatePolygonFromSceneGraph); create_pp->add_inData(&t->pp[i], sizeof(PolygonPack)); create_pp->add_inData(t->matrix, sizeof(float)*16); create_pp->add_inData(t->real_matrix, sizeof(float)*16); create_pp->add_inData(t->texture_info, sizeof(texture_list)); if ( (unsigned long)t->matrix & 0xf) { printf("marix not aligned\n"); } if ((unsigned long)t->real_matrix & 0xf) { printf("real_matrix not aligned\n"); } if ((unsigned long)t->texture_info & 0xf) { printf("texture_info not aligned\n"); } create_pp->add_outData(out_pp, sizeof(PolygonPack)); if (game_task_array != NULL) { create_pp->wait_for(game_task_array); } PolygonPackPtr tmp_pp = (PolygonPackPtr)manager->allocate(sizeof(PolygonPack)); tmp_pp->init(); create_pp->set_param(0, (memaddr)tmp_pp); out_pp = tmp_pp; create_pp->set_cpu(SPE_ANY); task_next->wait_for(create_pp); create_pp->spawn(); } } } void Viewer::rendering_sp(HTaskPtr task_next, SceneGraphRoot *sgroot) { int range_base = spe_num; // 切り上げのつもり int range = (r[spi].spackList_length + range_base - 1) / range_base; for (int i = 0; i < range_base; i++) { int index_start = range*i; int index_end = (index_start + range >= r[spi].spackList_length) ? r[spi].spackList_length : index_start + range; int starty = index_start*split_screen_h + 1; int endy = index_end*split_screen_h; if (starty<=0) starty = 1; if (endy>height) endy = height; HTaskPtr task_create_sp = manager->create_task(CreateSpan); task_create_sp->set_param(0,index_start); /** * ex. screen_height が 480, spenum が 6 の場合、各SPEのy担当範囲 * [ 1.. 80] [ 81..160] [161..240] * [241..320] [321..400] [401..480] * * ex. screen_height が 1080, spenum が 5 の場合、 * [ 1..216] [217..432] [433..648] * [649..864] [865..1080] */ task_create_sp->set_param(1,starty); task_create_sp->set_param(2,endy); task_create_sp->add_inData(r[ppi].ppack, sizeof(PolygonPack)); task_create_sp->add_inData(r[spi].spackList_ptr, sizeof(SpanPack*)*r[spi].spackList_length_align); task_create_sp->add_inData(&r[spi].spackList[index_start], sizeof(SpanPack)); task_next->wait_for(task_create_sp); task_create_sp->set_cpu(SPE_ANY); task_create_sp->spawn(); } } void Viewer::common_draw(HTaskPtr task_next) { //task_next = manager->create_task(Dummy); //task_next->set_post(post2runLoop, (void*)this); //Light info update int light_num = 4; int size = sizeof(float)*4*light_num; //xyz+alpha(4) * light_num(4) int light_size = size / sizeof(float); for (int i = 0; i < light_size; i++) { light_xyz[i] = light_xyz_stock[i]; } for (int i = 0; i < light_num; i++) { light_switch[i] = light_switch_stock[i]; } light_sysswitch[0] = light_sysswitch_stock; HTask *data_update_wait = 0; for (int i = 0; i < spe_num; i++) { data_update_wait = manager->create_task(DataUpdate); data_update_wait->set_param(0,3); data_update_wait->set_param(1,Light); // GlobalSet ID base data_update_wait->set_inData(0,light_xyz,size); // Light data_update_wait->set_inData(1,light_switch,light_num * sizeof(int)); // LightSwitch = Light+1 data_update_wait->set_inData(2,light_sysswitch,16); // LightSysSwitch = Light+2 data_update_wait->set_cpu((CPU_TYPE)(SPE_0+i)); data_update_wait->spawn(); } ppi ^= 1; r[ppi].ppack->clear(); for (int i = 0; i < r[spi].spackList_length; i++) { SpanPack *spack = &r[spi].spackList[i]; int startx = 1; int endx = split_screen_w; int starty = spack->info.y_top - split_screen_h + 1; //int endy = spack->info.y_top; int rangey = (starty + split_screen_h - 1 > this->height) ? this->height - starty + 1 : split_screen_h; #if 1 // mem_flag は spe 側で黒い部分を 0 で埋めるフラグ if(spack->info.size > 0 || mem_flag == 1) { int array_task_num = (this->width + split_screen_w - 1) / split_screen_w; HTaskPtr task_draw_array = manager->create_task_array(DrawSpan, array_task_num, 6, 1, rangey); Task *task_draw = 0; while (startx < this->width) { // Draw SpanPack task_draw = task_draw_array->next_task_array(DrawSpan,task_draw); task_draw->set_param(0,(memaddr)&pixels[(startx-1) + this->width*(starty-1)]); task_draw->set_param(1,this->width); task_draw->set_param(2,startx); task_draw->set_param(3,endx); task_draw->set_param(4,rangey); task_draw->set_param(5,spack->info.size); task_draw->set_inData(0,spack, sizeof(SpanPack)); for (int i = 0; i < rangey; i++) { task_draw->set_outData(i, &pixels[(startx-1) + this->width*(starty-1 + i) ], (endx-startx+1)*sizeof(int)); } startx += split_screen_w; endx += split_screen_w; if (endx > this->width) { endx = this->width; } } task_draw_array->spawn_task_array(task_draw->next()); task_draw_array->set_cpu(SPE_ANY); //task_next->wait_for(task_draw_array); task_draw_array->spawn(); } else { memset(&pixels[(startx-1)+this->width*(starty-1)], 0, (this->width)*sizeof(int)*rangey); } #else HTaskPtr task_draw; while (startx < this->width) { if (spack->info.size > 0) { // Draw SpanPack task_draw = manager->create_task(DrawSpan); task_draw->set_param(0, (memaddr)&pixels[(startx-1) + this->width*(starty-1)]); task_draw->set_param(1,this->width); task_draw->set_param(2,startx); task_draw->set_param(3,endx); task_draw->set_param(4,rangey); task_draw->set_param(5,spack->info.size); task_draw->add_inData(spack, sizeof(SpanPack)); for (int i = 0; i < rangey; i++) { task_draw->add_outData( &pixels[(startx-1) + this->width*(starty-1 + i) ], (endx-startx+1)*sizeof(int)); } } else { // 7.7.3 SL1 Data Cache Range Set to Zero コマンド // を使って、DMAでclearするべき... ということは、 // それもSPEでやる方が良い? memset(&pixels[(startx-1)+this->width*(starty-1)], 0, (this->width)*sizeof(int)*rangey); break; } task_draw->set_cpu(SPE_ANY); task_next->wait_for(task_draw); task_draw->spawn(); startx += split_screen_w; endx += split_screen_w; if (endx > this->width) { endx = this->width; } } #endif } spi ^= 1; for (int i = 1; i <= r[spi].spackList_length; i++) { r[spi].spackList[i-1].reinit(i*split_screen_h); } if (profile) { if (frames % 50 == 49) { manager->show_profile(); this_time = get_ticks(); if (this_time != start_time) { printf("\n%f FPS\n", ((((float)frames)*1000.0)/(this_time-start_time))); start_time = this_time; frames = 0; } } } } void Viewer::run_finish() { dev->free_device(); if (this_time != start_time) { printf("%f FPS\n", (((float)frames)/(this_time-start_time))*1000.0); } if (profile) { manager->show_profile(); } delete sgroot; // delete sgroot_2; quit(); } /* end */