diff --git a/Makefile b/Makefile index 68ca7bf..07752f3 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # SETUP -# apt-get install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev g++-7 +# sudo apt update; sudo apt-get install -y libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev g++-7 CPU_OBJ = $(addprefix build/cpu_obj/, ipu_host.o ipu_transfer.o i_system.o d_mode.o i_main.o m_argv.o m_misc.o net_common.o net_dedicated.o net_io.o net_packet.o net_query.o net_sdl.o net_server.o net_structrw.o aes_prng.o d_event.o d_iwad.o d_loop.o gusconf.o i_cdmus.o i_input.o i_joystick.o i_sdlmusic.o i_sdlsound.o i_sound.o i_timer.o i_video.o i_videohr.o midifile.o mus2mid.o m_bbox.o m_cheat.o m_config.o m_controls.o m_fixed.o net_client.o sha1.o memio.o tables.o v_video.o w_checksum.o w_main.o w_wad.o w_file.o w_file_stdc.o w_file_posix.o w_merge.o z_zone.o net_loop.o am_map.o d_items.o d_main.o d_net.o doomdef.o doomstat.o dstrings.o f_wipe.o g_game.o hu_lib.o hu_stuff.o info.o m_menu.o m_random.o p_ceilng.o p_doors.o p_enemy.o p_floor.o p_inter.o p_lights.o p_map.o p_maputl.o p_mobj.o p_plats.o p_pspr.o p_saveg.o p_setup.o p_sight.o p_spec.o p_switch.o p_telept.o p_tick.o p_user.o r_bsp.o r_data.o r_draw.o r_main.o r_plane.o r_segs.o r_sky.o r_things.o s_sound.o sounds.o st_lib.o st_stuff.o statdump.o wi_stuff.o) @@ -17,6 +17,9 @@ IPU_OBJ = $(addprefix build/ipu_obj/, \ p_setup.gp \ p_setup_codelets.gp \ p_tick.gp \ + r_bsp.gp \ + r_codelets.gp \ + r_main.gp \ tables.gp \ v_video.gp \ ) diff --git a/README.md b/README.md index f99725f..bef584f 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,17 @@ A WIP to put Doom 1993 on the IPU. +``` +# Install dependencies +sudo apt update; sudo apt-get install -y libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev g++-7 +# Build binary +make +# Download shareware resource pack +wget https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad +# Run +./build/doom -iwad doom1.wad -width 320 -nosound +``` + Activity Log: diff --git a/src/ipu/am_map.c b/src/ipu/am_map.c index 9bda67a..3a8f54b 100644 --- a/src/ipu/am_map.c +++ b/src/ipu/am_map.c @@ -223,7 +223,7 @@ static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF; static fixed_t scale_ftom; // JOSEF: Map only uses player position, so don't need reference to full -// player object (which will be on a different IPU tile). +// player object // May need mechanism for sending plr->message to rendering tile... LATER // static player_t *plr; // the player represented by an arrow IPUPlayerPos_t am_playerpos; diff --git a/src/ipu/ipu_interface.h b/src/ipu/ipu_interface.h index 6d52545..22f2b83 100644 --- a/src/ipu/ipu_interface.h +++ b/src/ipu/ipu_interface.h @@ -5,6 +5,7 @@ extern "C" { #endif #include "d_event.h" +#include "d_player.h" #include "doomdef.h" #include "doomtype.h" #include "m_fixed.h" @@ -43,6 +44,12 @@ typedef struct { // Other things for responder here } G_Responder_MiscValues_t; +typedef struct { + int displayplayer; + player_t players_displayplayer; + mobj_t displayplayer_mo; +} R_RenderPlayerView_MiscValues_t; + #ifdef __cplusplus diff --git a/src/ipu/ipu_transfer.c b/src/ipu/ipu_transfer.c index 500a7f2..ff761df 100644 --- a/src/ipu/ipu_transfer.c +++ b/src/ipu/ipu_transfer.c @@ -40,26 +40,9 @@ void IPU_Setup_UnpackMarkNums(const unsigned char* buf) { } } -/* -void IPU_UnpackVertexes(const unsigned char* buf) { - IpuPackedLevel_t* pack = (IpuPackedLevel_t*) buf; - uint32_t pos = 0; - numvertexes = *(uint32_t*)buf; - - mapvertex_t* ml = (mapvertex_t*)(&buf[4]); - vertex_t *li not done here; - for (int i = 0; i < numvertex) - vertexes = (vertex_t*) &pack->data[pos]; - pos += numvertexes * sizeof(vertex_t); - - numlines = pack->numlines; - lines = (line_t*) &pack->data[pos]; - pos += numlines * sizeof(line_t); - - // for (int i=0; i <) - // LATER: repoint other contents of lines - - -} - */ \ No newline at end of file +void IPU_R_RenderPlayerView_UnpackMiscValues(R_RenderPlayerView_MiscValues_t* pack) { + displayplayer = pack->displayplayer; + players[displayplayer] = pack->players_displayplayer; + // TODO: pack->displaypayer_mo +} \ No newline at end of file diff --git a/src/ipu/ipu_transfer.h b/src/ipu/ipu_transfer.h index c9a0a5a..a32a29d 100644 --- a/src/ipu/ipu_transfer.h +++ b/src/ipu/ipu_transfer.h @@ -16,6 +16,7 @@ extern unsigned char markbuf[IPUAMMARKBUFSIZE]; void IPU_G_LoadLevel_UnpackMiscValues(G_LoadLevel_MiscValues_t* pack); void IPU_G_Ticker_UnpackMiscValues(G_Ticker_MiscValues_t* pack); +void IPU_R_RenderPlayerView_UnpackMiscValues(R_RenderPlayerView_MiscValues_t* pack); #ifdef __cplusplus } diff --git a/src/ipu/p_setup.c b/src/ipu/p_setup.c index e9ee976..b2c64c8 100644 --- a/src/ipu/p_setup.c +++ b/src/ipu/p_setup.c @@ -9,6 +9,7 @@ #include "ipu_malloc.h" #include "ipu_transfer.h" #include "ipu_print.h" +#include "print.h" // @@ -140,6 +141,91 @@ void P_LoadSectors(const unsigned char *buf) { requestedlumpnum = gamelumpnum + ML_SIDEDEFS; } + +// +// P_LoadNodes +// +__attribute__((optnone)) // Workaround for https://graphcore.atlassian.net/browse/LLVM-330 +void P_LoadNodes(const unsigned char *buf) { + int i; + int j; + int k; + mapnode_t *mn; + node_t *no; + + int lumplen = ((int*)buf)[0]; + numnodes = lumplen / sizeof(mapnode_t); + nodes = IPU_level_malloc(numnodes * sizeof(node_t)); + memset(nodes, 0, numnodes * sizeof(node_t)); + + mn = (mapnode_t *)(&buf[sizeof(int)]); + no = nodes; + + for (i = 0; i < numnodes; i++, no++, mn++) { + no->x = SHORT(mn->x) << FRACBITS; + no->y = SHORT(mn->y) << FRACBITS; + no->dx = SHORT(mn->dx) << FRACBITS; + no->dy = SHORT(mn->dy) << FRACBITS; + for (j = 0; j < 2; j++) { + no->children[j] = SHORT(mn->children[j]); + for (k = 0; k < 4; k++) { + no->bbox[j][k] = SHORT(mn->bbox[j][k]) << FRACBITS; + } + } + } + +} + +// +// P_LoadThings +// +void P_LoadThings(const unsigned char *buf) { + byte *data; + int i; + mapthing_t *mt; + mapthing_t spawnthing; + int numthings; + boolean spawn; + + int lumplen = ((int*)buf)[0]; + numthings = lumplen / sizeof(mapthing_t); + + mt = (mapthing_t *)(&buf[sizeof(int)]); + for (i = 0; i < numthings; i++, mt++) { + spawn = true; + + // Do not spawn cool, new monsters if !commercial + if (gamemode != commercial) { + switch (SHORT(mt->type)) { + case 68: // Arachnotron + case 64: // Archvile + case 88: // Boss Brain + case 89: // Boss Shooter + case 69: // Hell Knight + case 67: // Mancubus + case 71: // Pain Elemental + case 65: // Former Human Commando + case 66: // Revenant + case 84: // Wolf SS + spawn = false; + break; + } + } + if (spawn == false) + break; + + // Do spawn all other stuff. + spawnthing.x = SHORT(mt->x); + spawnthing.y = SHORT(mt->y); + spawnthing.angle = SHORT(mt->angle); + spawnthing.type = SHORT(mt->type); + spawnthing.options = SHORT(mt->options); + + // P_SpawnMapThing(&spawnthing); // TODO + } + +} + // // P_LoadSideDefs // @@ -167,7 +253,7 @@ void P_LoadSideDefs(const unsigned char *buf) { sd->sector = §ors[SHORT(msd->sector)]; } - requestedlumpnum = gamelumpnum + ML_LINEDEFS; + requestedlumpnum = gamelumpnum + ML_LINEDEFS; // JOSEF: Get rid of this } // @@ -238,18 +324,6 @@ void P_LoadLineDefs(const unsigned char *buf) { else ld->backsector = 0; } - - // msd = (mapsidedef_t *)(&buf[sizeof(int)]); - ipuprint("numlines: "); - ipuprintnum(numlines); - ipuprint(", sidenum0: "); - ipuprintnum(lines[0].sidenum[1]); - ipuprint(", sidenum-1: "); - ipuprintnum(lines[numlines-1].sidenum[1]); - ipuprint(", dx-1: "); - ipuprintnum(lines[numlines-1].dx); - ipuprint("\n"); - requestedlumpnum = gamelumpnum + ML_SSECTORS; } @@ -281,7 +355,7 @@ void P_LoadSubsectors(const unsigned char *buf) { // // P_SetupLevel // -void P_SetupLevel_pt0(void) { +void P_SetupLevel_pt0(const unsigned char unused) { int i; /* LATER diff --git a/src/ipu/p_setup_codelets.cpp b/src/ipu/p_setup_codelets.cpp index b09b2c7..a68daf3 100644 --- a/src/ipu/p_setup_codelets.cpp +++ b/src/ipu/p_setup_codelets.cpp @@ -1,99 +1,66 @@ #include +#include + +#include "doomdata.h" + #include "ipu_transfer.h" extern "C" { - void P_SetupLevel_pt0(void); + void P_SetupLevel_pt0(const unsigned char *buf); void P_LoadBlockMap(const unsigned char *buf); void P_LoadVertexes(const unsigned char *buf); void P_LoadSectors(const unsigned char *buf); void P_LoadSideDefs(const unsigned char *buf); void P_LoadLineDefs(const unsigned char *buf); void P_LoadSubsectors(const unsigned char *buf); + void P_LoadNodes(const unsigned char *buf); + void P_LoadThings(const unsigned char *buf); void IPU_Setup_UnpackMarkNums(const unsigned char* buf); }; // --------------- P_Setup ----------------- // -class P_SetupLevel_pt0_Vertex : public poplar::Vertex { - poplar::Output lumpNum; - public: - bool compute() { - P_SetupLevel_pt0(); - *lumpNum = requestedlumpnum; - return true; - } +struct P_SetupLevel_SubFunc { + void (*func)(const unsigned char*); + int lump_num; +}; +static P_SetupLevel_SubFunc setupLevelSubfuncs[14] = { + {P_SetupLevel_pt0, 0}, + {P_LoadBlockMap, ML_BLOCKMAP}, + {P_LoadVertexes, ML_VERTEXES}, + {P_LoadSectors, ML_SECTORS}, + {P_LoadSideDefs, ML_SIDEDEFS}, + {P_LoadLineDefs, ML_LINEDEFS}, + {P_LoadSubsectors, ML_SSECTORS}, + {P_LoadNodes, ML_NODES}, + // {P_LoadSegs, ML_SEGS}, + // {P_GroupLines, ML_SEGS}, + // {P_LoadReject, ML_REJECT}, + {P_LoadThings, ML_THINGS}, + // {P_SpawnSpecials, 0} + {NULL, 0}, /* SENTINEL */ }; - -class P_LoadBlockMap_Vertex : public poplar::Vertex { +// THIS IS CALLING VIA A POINTER. THAT'S PROBABLY BAD... +class P_SetupLevel_Vertex : public poplar::Vertex { poplar::Input> lumpBuf; poplar::Output lumpNum; public: bool compute() { - P_LoadBlockMap(&lumpBuf[0]); - *lumpNum = requestedlumpnum; + static int step = 0; + setupLevelSubfuncs[step].func(&lumpBuf[0]); + step += 1; + *lumpNum = gamelumpnum + setupLevelSubfuncs[step].lump_num; + if (setupLevelSubfuncs[step].func == NULL) { + step = 0; + } return true; } }; -class P_LoadVertexes_Vertex : public poplar::Vertex { - poplar::Input> lumpBuf; - poplar::Output lumpNum; - public: - bool compute() { - P_LoadVertexes(&lumpBuf[0]); - *lumpNum = requestedlumpnum; - return true; - } -}; - -class P_LoadSectors_Vertex : public poplar::Vertex { - poplar::Input> lumpBuf; - poplar::Output lumpNum; - public: - bool compute() { - P_LoadSectors(&lumpBuf[0]); - *lumpNum = requestedlumpnum; - return true; - } -}; - -class P_LoadSideDefs_Vertex : public poplar::Vertex { - poplar::Input> lumpBuf; - poplar::Output lumpNum; - public: - bool compute() { - P_LoadSideDefs(&lumpBuf[0]); - *lumpNum = requestedlumpnum; - return true; - } -}; - -class P_LoadLineDefs_Vertex : public poplar::Vertex { - poplar::Input> lumpBuf; - poplar::Output lumpNum; - public: - bool compute() { - P_LoadLineDefs(&lumpBuf[0]); - *lumpNum = requestedlumpnum; - return true; - } -}; - - -class P_LoadSubsectors_Vertex : public poplar::Vertex { - poplar::Input> lumpBuf; - poplar::Output lumpNum; - public: - bool compute() { - P_LoadSubsectors(&lumpBuf[0]); - *lumpNum = requestedlumpnum; - return true; - } -}; // ------------ IPU_Setup ------------ // diff --git a/src/ipu/r_bsp.c b/src/ipu/r_bsp.c new file mode 100644 index 0000000..961ed4a --- /dev/null +++ b/src/ipu/r_bsp.c @@ -0,0 +1,497 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// DESCRIPTION: +// BSP traversal, handling of LineSegs for rendering. +// + +#include + +#include "doomdata.h" +// State. +#include "doomstat.h" +#include "doomtype.h" +#include "i_system.h" +#include "i_video.h" +#include "m_bbox.h" +#include "m_fixed.h" +#include "r_defs.h" +#include "r_main.h" +#include "r_plane.h" +#include "r_state.h" +#include "r_things.h" +#include "tables.h" + +//#include "r_local.h" + +seg_t *curline; +side_t *sidedef; +line_t *linedef; +sector_t *frontsector; +sector_t *backsector; + +drawseg_t drawsegs[MAXDRAWSEGS]; +drawseg_t *ds_p; + +void R_StoreWallRange(int start, int stop); + +// +// R_ClearDrawSegs +// +void R_ClearDrawSegs(void) { ds_p = drawsegs; } + +// +// ClipWallSegment +// Clips the given range of columns +// and includes it in the new clip list. +// +typedef struct { + int first; + int last; + +} cliprange_t; + +// We must expand MAXSEGS to the theoretical limit of the number of solidsegs +// that can be generated in a scene by the DOOM engine. This was determined by +// Lee Killough during BOOM development to be a function of the screensize. +// The simplest thing we can do, other than fix this bug, is to let the game +// render overage and then bomb out by detecting the overflow after the +// fact. -haleyjd +//#define MAXSEGS 32 +#define MAXSEGS (SCREENWIDTH / 2 + 1) + +// newend is one past the last valid seg +cliprange_t *newend; +cliprange_t solidsegs[MAXSEGS]; + +// +// R_ClipSolidWallSegment +// Does handle solid walls, +// e.g. single sided LineDefs (middle texture) +// that entirely block the view. +// +void R_ClipSolidWallSegment(int first, int last) { + cliprange_t *next; + cliprange_t *start; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) { + if (last < start->first - 1) { + // Post is entirely visible (above start), + // so insert a new clippost. + R_StoreWallRange(first, last); + next = newend; + newend++; + + while (next != start) { + *next = *(next - 1); + next--; + } + next->first = first; + next->last = last; + return; + } + + // There is a fragment above *start. + R_StoreWallRange(first, start->first - 1); + // Now adjust the clip size. + start->first = first; + } + + // Bottom contained in start? + if (last <= start->last) + return; + + next = start; + while (last >= (next + 1)->first - 1) { + // There is a fragment between two posts. + R_StoreWallRange(next->last + 1, (next + 1)->first - 1); + next++; + + if (last <= next->last) { + // Bottom is contained in next. + // Adjust the clip size. + start->last = next->last; + goto crunch; + } + } + + // There is a fragment after *next. + R_StoreWallRange(next->last + 1, last); + // Adjust the clip size. + start->last = last; + +// Remove start+1 to next from the clip list, +// because start now covers their area. +crunch: + if (next == start) { + // Post just extended past the bottom of one post. + return; + } + + while (next++ != newend) { + // Remove a post. + *++start = *next; + } + + newend = start + 1; +} + +// +// R_ClipPassWallSegment +// Clips the given range of columns, +// but does not includes it in the clip list. +// Does handle windows, +// e.g. LineDefs with upper and lower texture. +// +void R_ClipPassWallSegment(int first, int last) { + cliprange_t *start; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) { + if (last < start->first - 1) { + // Post is entirely visible (above start). + R_StoreWallRange(first, last); + return; + } + + // There is a fragment above *start. + R_StoreWallRange(first, start->first - 1); + } + + // Bottom contained in start? + if (last <= start->last) + return; + + while (last >= (start + 1)->first - 1) { + // There is a fragment between two posts. + R_StoreWallRange(start->last + 1, (start + 1)->first - 1); + start++; + + if (last <= start->last) + return; + } + + // There is a fragment after *next. + R_StoreWallRange(start->last + 1, last); +} + +// +// R_ClearClipSegs +// +void R_ClearClipSegs(void) { + solidsegs[0].first = -0x7fffffff; + solidsegs[0].last = -1; + solidsegs[1].first = viewwidth; + solidsegs[1].last = 0x7fffffff; + newend = solidsegs + 2; +} + +// +// R_AddLine +// Clips the given segment +// and adds any visible pieces to the line list. +// +void R_AddLine(seg_t *line) { + int x1; + int x2; + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + + curline = line; + + // OPTIMIZE: quickly reject orthogonal back sides. + angle1 = R_PointToAngle(line->v1->x, line->v1->y); + angle2 = R_PointToAngle(line->v2->x, line->v2->y); + + // Clip to view edges. + // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). + span = angle1 - angle2; + + // Back side? I.e. backface culling? + if (span >= ANG180) + return; + + // Global angle needed by segcalc. + rw_angle1 = angle1; + angle1 -= viewangle; + angle2 -= viewangle; + + tspan = angle1 + clipangle; + if (tspan > 2 * clipangle) { + tspan -= 2 * clipangle; + + // Totally off the left edge? + if (tspan >= span) + return; + + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2 * clipangle) { + tspan -= 2 * clipangle; + + // Totally off the left edge? + if (tspan >= span) + return; + angle2 = -clipangle; + } + + // The seg is in the view range, + // but not necessarily visible. + angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; + angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; + x1 = viewangletox[angle1]; + x2 = viewangletox[angle2]; + + // Does not cross a pixel? + if (x1 == x2) + return; + + backsector = line->backsector; + + // Single sided line? + if (!backsector) + goto clipsolid; + + // Closed door. + if (backsector->ceilingheight <= frontsector->floorheight || + backsector->floorheight >= frontsector->ceilingheight) + goto clipsolid; + + // Window. + if (backsector->ceilingheight != frontsector->ceilingheight || + backsector->floorheight != frontsector->floorheight) + goto clippass; + + // Reject empty lines used for triggers + // and special events. + // Identical floor and ceiling on both sides, + // identical light levels on both sides, + // and no middle texture. + if (backsector->ceilingpic == frontsector->ceilingpic && + backsector->floorpic == frontsector->floorpic && + backsector->lightlevel == frontsector->lightlevel && + curline->sidedef->midtexture == 0) { + return; + } + +clippass: + R_ClipPassWallSegment(x1, x2 - 1); + return; + +clipsolid: + R_ClipSolidWallSegment(x1, x2 - 1); +} + +// +// R_CheckBBox +// Checks BSP node/subtree bounding box. +// Returns true +// if some part of the bbox might be visible. +// +int checkcoord[12][4] = {{3, 0, 2, 1}, {3, 0, 2, 0}, {3, 1, 2, 0}, {0}, + {2, 0, 2, 1}, {0, 0, 0, 0}, {3, 1, 3, 0}, {0}, + {2, 0, 3, 1}, {2, 1, 3, 1}, {2, 1, 3, 0}}; + +boolean R_CheckBBox(fixed_t *bspcoord) { + int boxx; + int boxy; + int boxpos; + + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + + cliprange_t *start; + + int sx1; + int sx2; + + // Find the corners of the box + // that define the edges from current viewpoint. + if (viewx <= bspcoord[BOXLEFT]) + boxx = 0; + else if (viewx < bspcoord[BOXRIGHT]) + boxx = 1; + else + boxx = 2; + + if (viewy >= bspcoord[BOXTOP]) + boxy = 0; + else if (viewy > bspcoord[BOXBOTTOM]) + boxy = 1; + else + boxy = 2; + + boxpos = (boxy << 2) + boxx; + if (boxpos == 5) + return true; + + x1 = bspcoord[checkcoord[boxpos][0]]; + y1 = bspcoord[checkcoord[boxpos][1]]; + x2 = bspcoord[checkcoord[boxpos][2]]; + y2 = bspcoord[checkcoord[boxpos][3]]; + + // check clip list for an open space + angle1 = R_PointToAngle(x1, y1) - viewangle; + angle2 = R_PointToAngle(x2, y2) - viewangle; + + span = angle1 - angle2; + + // Sitting on a line? + if (span >= ANG180) + return true; + + tspan = angle1 + clipangle; + + if (tspan > 2 * clipangle) { + tspan -= 2 * clipangle; + + // Totally off the left edge? + if (tspan >= span) + return false; + + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2 * clipangle) { + tspan -= 2 * clipangle; + + // Totally off the left edge? + if (tspan >= span) + return false; + + angle2 = -clipangle; + } + + // Find the first clippost + // that touches the source post + // (adjacent pixels are touching). + angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; + angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; + sx1 = viewangletox[angle1]; + sx2 = viewangletox[angle2]; + + // Does not cross a pixel. + if (sx1 == sx2) + return false; + sx2--; + + start = solidsegs; + while (start->last < sx2) + start++; + + if (sx1 >= start->first && sx2 <= start->last) { + // The clippost contains the new span. + return false; + } + + return true; +} + +// +// R_Subsector +// Determine floor/ceiling planes. +// Add sprites of things in sector. +// Draw one or more line segments. +// +void R_Subsector(int num) { + int count; + seg_t *line; + subsector_t *sub; + + if (num >= numsubsectors) + I_Error("R_Subsector: ss %i with numss = %i", num, numsubsectors); + + sscount++; + sub = &subsectors[num]; + frontsector = sub->sector; + count = sub->numlines; + line = &segs[sub->firstline]; + + if (frontsector->floorheight < viewz) { + floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, + frontsector->lightlevel); + } else + floorplane = NULL; + + if (frontsector->ceilingheight > viewz || + frontsector->ceilingpic == skyflatnum) { + ceilingplane = + R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, + frontsector->lightlevel); + } else + ceilingplane = NULL; + + R_AddSprites(frontsector); + + while (count--) { + R_AddLine(line); + line++; + } + + // check for solidsegs overflow - extremely unsatisfactory! + if (newend > &solidsegs[32]) + I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); +} + +// +// RenderBSPNode +// Renders all subsectors below a given node, +// traversing subtree recursively. +// Just call with BSP root. +void R_RenderBSPNode(int bspnum) { + node_t *bsp; + int side; + + // Found a subsector? + if (bspnum & NF_SUBSECTOR) { + if (bspnum == -1) + R_Subsector(0); + else + R_Subsector(bspnum & (~NF_SUBSECTOR)); + return; + } + + bsp = &nodes[bspnum]; + + // Decide which side the view point is on. + side = R_PointOnSide(viewx, viewy, bsp); + + // Recursively divide front space. + R_RenderBSPNode(bsp->children[side]); + + // Possibly divide back space. + if (R_CheckBBox(bsp->bbox[side ^ 1])) + R_RenderBSPNode(bsp->children[side ^ 1]); +} diff --git a/src/ipu/r_codelets.cpp b/src/ipu/r_codelets.cpp new file mode 100644 index 0000000..24856fe --- /dev/null +++ b/src/ipu/r_codelets.cpp @@ -0,0 +1,33 @@ +#include + +#include + +// #include "doomdata.h" + +#include "ipu_transfer.h" + + +extern "C" { + // void P_SetupLevel_pt0(const unsigned char *buf); +}; + + +// --------------- P_Setup ----------------- // + +struct R_RenderPlayerView_Vertex : public poplar::Vertex { + poplar::Input> miscValues; + poplar::InOut> frame; + + void compute() { + // printf("Running R_RenderPlayerView_Vertex\n"); + // AM_Drawer(&frame[0]); + for (int i = 0; i < 100; ++i){ + frame[i + 320 * i ] = 1; + frame[i + 320 * i + 1] = 1; + } + IPU_R_RenderPlayerView_UnpackMiscValues( + (R_RenderPlayerView_MiscValues_t*) &miscValues[0] + ); + return ; + } +}; diff --git a/src/ipu/r_main.c b/src/ipu/r_main.c new file mode 100644 index 0000000..71e3f7f --- /dev/null +++ b/src/ipu/r_main.c @@ -0,0 +1,760 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// DESCRIPTION: +// Rendering main loop and setup functions, +// utility functions (BSP, geometry, trigonometry). +// See tables.c, too. +// + +// #include // JOSEF +// #include + + + +#include "d_loop.h" +#include "d_player.h" +#include "doomdata.h" +#include "doomtype.h" +#include "i_video.h" +#include "m_bbox.h" +#include "m_fixed.h" +#include "m_menu.h" +#include "p_mobj.h" +#include "r_bsp.h" +#include "r_data.h" +#include "r_defs.h" +#include "r_draw.h" +#include "r_main.h" +#include "r_plane.h" +#include "r_sky.h" +#include "r_state.h" +#include "r_things.h" +#include "tables.h" + +// JOSEF: added +inline int abs(int x) { + return (x < 0) ? -x : x; +} + +// Fineangles in the SCREENWIDTH wide window. +#define FIELDOFVIEW 2048 + +int viewangleoffset; + +// increment every time a check is made +int validcount = 1; + +lighttable_t *fixedcolormap; +extern lighttable_t **walllights; + +int centerx; +int centery; + +fixed_t centerxfrac; +fixed_t centeryfrac; +fixed_t projection; + +// just for profiling purposes +int framecount; + +int sscount; +int linecount; +int loopcount; + +fixed_t viewx; +fixed_t viewy; +fixed_t viewz; + +angle_t viewangle; + +fixed_t viewcos; +fixed_t viewsin; + +player_t *viewplayer; + +// 0 = high, 1 = low +int detailshift; + +// +// precalculated math tables +// +angle_t clipangle; + +// The viewangletox[viewangle + FINEANGLES/4] lookup +// maps the visible view angles to screen X coordinates, +// flattening the arc to a flat projection plane. +// There will be many angles mapped to the same X. +int viewangletox[FINEANGLES / 2]; + +// The xtoviewangleangle[] table maps a screen pixel +// to the lowest viewangle that maps back to x ranges +// from clipangle to -clipangle. +angle_t xtoviewangle[SCREENWIDTH + 1]; + +// lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; // JOSEF: TODO +// lighttable_t *scalelightfixed[MAXLIGHTSCALE]; // JOSEF: TODO +// lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // JOSEF: TODO + +// bumped light from gun blasts +int extralight; + +void (*colfunc)(void); +void (*basecolfunc)(void); +void (*fuzzcolfunc)(void); +void (*transcolfunc)(void); +void (*spanfunc)(void); + +/* +// +// R_AddPointToBox +// Expand a given bbox +// so that it encloses a given point. +// +void R_AddPointToBox(int x, int y, fixed_t *box) { + if (x < box[BOXLEFT]) + box[BOXLEFT] = x; + if (x > box[BOXRIGHT]) + box[BOXRIGHT] = x; + if (y < box[BOXBOTTOM]) + box[BOXBOTTOM] = y; + if (y > box[BOXTOP]) + box[BOXTOP] = y; +} + +// +// R_PointOnSide +// Traverse BSP (sub) tree, +// check point against partition plane. +// Returns side 0 (front) or 1 (back). +// +int R_PointOnSide(fixed_t x, fixed_t y, node_t *node) { + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!node->dx) { + if (x <= node->x) + return node->dy > 0; + + return node->dy < 0; + } + if (!node->dy) { + if (y <= node->y) + return node->dx < 0; + + return node->dx > 0; + } + + dx = (x - node->x); + dy = (y - node->y); + + // Try to quickly decide by looking at sign bits. + if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000) { + if ((node->dy ^ dx) & 0x80000000) { + // (left is negative) + return 1; + } + return 0; + } + + left = FixedMul(node->dy >> FRACBITS, dx); + right = FixedMul(dy, node->dx >> FRACBITS); + + if (right < left) { + // front side + return 0; + } + // back side + return 1; +} + +int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line) { + fixed_t lx; + fixed_t ly; + fixed_t ldx; + fixed_t ldy; + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + lx = line->v1->x; + ly = line->v1->y; + + ldx = line->v2->x - lx; + ldy = line->v2->y - ly; + + if (!ldx) { + if (x <= lx) + return ldy > 0; + + return ldy < 0; + } + if (!ldy) { + if (y <= ly) + return ldx < 0; + + return ldx > 0; + } + + dx = (x - lx); + dy = (y - ly); + + // Try to quickly decide by looking at sign bits. + if ((ldy ^ ldx ^ dx ^ dy) & 0x80000000) { + if ((ldy ^ dx) & 0x80000000) { + // (left is negative) + return 1; + } + return 0; + } + + left = FixedMul(ldy >> FRACBITS, dx); + right = FixedMul(dy, ldx >> FRACBITS); + + if (right < left) { + // front side + return 0; + } + // back side + return 1; +} + +// +// R_PointToAngle +// To get a global angle from cartesian coordinates, +// the coordinates are flipped until they are in +// the first octant of the coordinate system, then +// the y (<=x) is scaled and divided by x to get a +// tangent (slope) value which is looked up in the +// tantoangle[] table. + +// + +angle_t R_PointToAngle(fixed_t x, fixed_t y) { + x -= viewx; + y -= viewy; + + if ((!x) && (!y)) + return 0; + + if (x >= 0) { + // x >=0 + if (y >= 0) { + // y>= 0 + + if (x > y) { + // octant 0 + return tantoangle[SlopeDiv(y, x)]; + } else { + // octant 1 + return ANG90 - 1 - tantoangle[SlopeDiv(x, y)]; + } + } else { + // y<0 + y = -y; + + if (x > y) { + // octant 8 + return -tantoangle[SlopeDiv(y, x)]; + } else { + // octant 7 + return ANG270 + tantoangle[SlopeDiv(x, y)]; + } + } + } else { + // x<0 + x = -x; + + if (y >= 0) { + // y>= 0 + if (x > y) { + // octant 3 + return ANG180 - 1 - tantoangle[SlopeDiv(y, x)]; + } else { + // octant 2 + return ANG90 + tantoangle[SlopeDiv(x, y)]; + } + } else { + // y<0 + y = -y; + + if (x > y) { + // octant 4 + return ANG180 + tantoangle[SlopeDiv(y, x)]; + } else { + // octant 5 + return ANG270 - 1 - tantoangle[SlopeDiv(x, y)]; + } + } + } + return 0; +} + +angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) { + viewx = x1; + viewy = y1; + + return R_PointToAngle(x2, y2); +} + +fixed_t R_PointToDist(fixed_t x, fixed_t y) { + int angle; + fixed_t dx; + fixed_t dy; + fixed_t temp; + fixed_t dist; + fixed_t frac; + + dx = abs(x - viewx); + dy = abs(y - viewy); + + if (dy > dx) { + temp = dx; + dx = dy; + dy = temp; + } + + // Fix crashes in udm1.wad + + if (dx != 0) { + frac = FixedDiv(dy, dx); + } else { + frac = 0; + } + + angle = (tantoangle[frac >> DBITS] + ANG90) >> ANGLETOFINESHIFT; + + // use as cosine + dist = FixedDiv(dx, finesine[angle]); + + return dist; +} + +// +// R_InitPointToAngle +// +void R_InitPointToAngle(void) { +// UNUSED - now getting from tables.c +#if 0 + int i; + long t; + float f; +// +// slope (tangent) to angle lookup +// + for (i=0 ; i<=SLOPERANGE ; i++) + { + f = atan( (float)i/SLOPERANGE )/(3.141592657*2); + t = 0xffffffff*f; + tantoangle[i] = t; + } +#endif +} + +// +// R_ScaleFromGlobalAngle +// Returns the texture mapping scale +// for the current line (horizontal span) +// at the given angle. +// rw_distance must be calculated first. +// +fixed_t R_ScaleFromGlobalAngle(angle_t visangle) { + fixed_t scale; + angle_t anglea; + angle_t angleb; + int sinea; + int sineb; + fixed_t num; + int den; + +// UNUSED +#if 0 +{ + fixed_t dist; + fixed_t z; + fixed_t sinv; + fixed_t cosv; + + sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT]; + dist = FixedDiv (rw_distance, sinv); + cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT]; + z = abs(FixedMul (dist, cosv)); + scale = FixedDiv(projection, z); + return scale; +} +#endif + + anglea = ANG90 + (visangle - viewangle); + angleb = ANG90 + (visangle - rw_normalangle); + + // both sines are allways positive + sinea = finesine[anglea >> ANGLETOFINESHIFT]; + sineb = finesine[angleb >> ANGLETOFINESHIFT]; + num = FixedMul(projection, sineb) << detailshift; + den = FixedMul(rw_distance, sinea); + + if (den > num >> FRACBITS) { + scale = FixedDiv(num, den); + + if (scale > 64 * FRACUNIT) + scale = 64 * FRACUNIT; + else if (scale < 256) + scale = 256; + } else + scale = 64 * FRACUNIT; + + return scale; +} + +// +// R_InitTables +// +void R_InitTables(void) { +// UNUSED: now getting from tables.c +#if 0 + int i; + float a; + float fv; + int t; + + // viewangle tangent table + for (i=0 ; i FRACUNIT * 2) + t = -1; + else if (finetangent[i] < -FRACUNIT * 2) + t = viewwidth + 1; + else { + t = FixedMul(finetangent[i], focallength); + t = (centerxfrac - t + FRACUNIT - 1) >> FRACBITS; + + if (t < -1) + t = -1; + else if (t > viewwidth + 1) + t = viewwidth + 1; + } + viewangletox[i] = t; + } + + // Scan viewangletox[] to generate xtoviewangle[]: + // xtoviewangle will give the smallest view angle + // that maps to x. + for (x = 0; x <= viewwidth; x++) { + i = 0; + while (viewangletox[i] > x) + i++; + xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANG90; + } + + // Take out the fencepost cases from viewangletox. + for (i = 0; i < FINEANGLES / 2; i++) { + t = FixedMul(finetangent[i], focallength); + t = centerx - t; + + if (viewangletox[i] == -1) + viewangletox[i] = 0; + else if (viewangletox[i] == viewwidth + 1) + viewangletox[i] = viewwidth; + } + + clipangle = xtoviewangle[0]; +} + +// +// R_InitLightTables +// Only inits the zlight table, +// because the scalelight table changes with view size. +// +#define DISTMAP 2 + +void R_InitLightTables(void) { + int i; + int j; + int level; + int startmap; + int scale; + + // Calculate the light levels to use + // for each level / distance combination. + for (i = 0; i < LIGHTLEVELS; i++) { + startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; + for (j = 0; j < MAXLIGHTZ; j++) { + scale = FixedDiv((SCREENWIDTH / 2 * FRACUNIT), (j + 1) << LIGHTZSHIFT); + scale >>= LIGHTSCALESHIFT; + level = startmap - scale / DISTMAP; + + if (level < 0) + level = 0; + + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS - 1; + + zlight[i][j] = colormaps + level * 256; + } + } +} + +// +// R_SetViewSize +// Do not really change anything here, +// because it might be in the middle of a refresh. +// The change will take effect next refresh. +// +boolean setsizeneeded; +int setblocks; +int setdetail; + +void R_SetViewSize(int blocks, int detail) { + setsizeneeded = true; + setblocks = blocks; + setdetail = detail; +} + +// +// R_ExecuteSetViewSize +// +void R_ExecuteSetViewSize(void) { + fixed_t cosadj; + fixed_t dy; + int i; + int j; + int level; + int startmap; + + setsizeneeded = false; + + if (setblocks == 11) { + scaledviewwidth = SCREENWIDTH; + viewheight = SCREENHEIGHT; + } else { + scaledviewwidth = setblocks * 32; + viewheight = (setblocks * 168 / 10) & ~7; + } + + detailshift = setdetail; + viewwidth = scaledviewwidth >> detailshift; + + centery = viewheight / 2; + centerx = viewwidth / 2; + centerxfrac = centerx << FRACBITS; + centeryfrac = centery << FRACBITS; + projection = centerxfrac; + + if (!detailshift) { + colfunc = basecolfunc = R_DrawColumn; + fuzzcolfunc = R_DrawFuzzColumn; + transcolfunc = R_DrawTranslatedColumn; + spanfunc = R_DrawSpan; + } else { + colfunc = basecolfunc = R_DrawColumnLow; + fuzzcolfunc = R_DrawFuzzColumnLow; + transcolfunc = R_DrawTranslatedColumnLow; + spanfunc = R_DrawSpanLow; + } + + R_InitBuffer(scaledviewwidth, viewheight); + + R_InitTextureMapping(); + + // psprite scales + pspritescale = FRACUNIT * viewwidth / SCREENWIDTH; + pspriteiscale = FRACUNIT * SCREENWIDTH / viewwidth; + + // thing clipping + for (i = 0; i < viewwidth; i++) + screenheightarray[i] = viewheight; + + // planes + for (i = 0; i < viewheight; i++) { + dy = ((i - viewheight / 2) << FRACBITS) + FRACUNIT / 2; + dy = abs(dy); + yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, dy); + } + + for (i = 0; i < viewwidth; i++) { + cosadj = abs(finecosine[xtoviewangle[i] >> ANGLETOFINESHIFT]); + distscale[i] = FixedDiv(FRACUNIT, cosadj); + } + + // Calculate the light levels to use + // for each level / scale combination. + for (i = 0; i < LIGHTLEVELS; i++) { + startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; + for (j = 0; j < MAXLIGHTSCALE; j++) { + level = startmap - j * SCREENWIDTH / (viewwidth << detailshift) / DISTMAP; + + if (level < 0) + level = 0; + + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS - 1; + + scalelight[i][j] = colormaps + level * 256; + } + } +} + +// +// R_Init +// + +void R_Init(void) { + R_InitData(); + // printf("."); // JOSEF + R_InitPointToAngle(); + // printf("."); // JOSEF + R_InitTables(); + // viewwidth / viewheight / detailLevel are set by the defaults + // printf("."); // JOSEF + + R_SetViewSize(screenblocks, detailLevel); + R_InitPlanes(); + // printf("."); // JOSEF + R_InitLightTables(); + // printf("."); // JOSEF + R_InitSkyMap(); + R_InitTranslationTables(); + // printf("."); // JOSEF + + framecount = 0; +} + +// +// R_PointInSubsector +// +subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) { + node_t *node; + int side; + int nodenum; + + // single subsector is a special case + if (!numnodes) + return subsectors; + + nodenum = numnodes - 1; + + while (!(nodenum & NF_SUBSECTOR)) { + node = &nodes[nodenum]; + side = R_PointOnSide(x, y, node); + nodenum = node->children[side]; + } + + return &subsectors[nodenum & ~NF_SUBSECTOR]; +} +*/ + +// +// R_SetupFrame +// +void R_SetupFrame(player_t *player) { + int i; + + viewplayer = player; + viewx = player->mo->x; + viewy = player->mo->y; + viewangle = player->mo->angle + viewangleoffset; + extralight = player->extralight; + + viewz = player->viewz; + + viewsin = finesine[viewangle >> ANGLETOFINESHIFT]; + viewcos = finecosine[viewangle >> ANGLETOFINESHIFT]; + + sscount = 0; + + if (player->fixedcolormap) { + fixedcolormap = colormaps + player->fixedcolormap * 256; + + walllights = scalelightfixed; + + for (i = 0; i < MAXLIGHTSCALE; i++) + scalelightfixed[i] = fixedcolormap; + } else + fixedcolormap = 0; + + framecount++; + validcount++; +} + + +// +// R_RenderView +// +void R_RenderPlayerView(player_t *player) { + R_SetupFrame(player); + + // Clear buffers. + // R_ClearClipSegs(); // TODO + // R_ClearDrawSegs(); // TODO + // R_ClearPlanes(); // TODO + // R_ClearSprites(); // TODO + + // check for new console commands. + // NetUpdate(); // TODO + + // The head node is the last node output. + // R_RenderBSPNode(numnodes - 1); // TODO + + // Check for new console commands. + // NetUpdate(); // TODO + + // R_DrawPlanes(); // TODO + + // Check for new console commands. + // NetUpdate(); // TODO + + // R_DrawMasked(); // TODO + + // Check for new console commands. + // NetUpdate(); // TODO +} diff --git a/src/ipu_host.cpp b/src/ipu_host.cpp index 2fc2c51..6a5e69b 100644 --- a/src/ipu_host.cpp +++ b/src/ipu_host.cpp @@ -1,3 +1,6 @@ +// Yes, I know this file is full of awful unnecessary boilerplate and interfaces, the +// structure of the IPU<->Host interface is evolving __somewhat organically__ ... + #include "ipu_host.h" #include @@ -39,6 +42,7 @@ class IpuDoom { void buildIpuGraph(); void run_AM_Drawer(); + void run_R_RenderPlayerView(); void run_IPU_Setup(); void run_G_DoLoadLevel(); void run_G_Ticker(); @@ -57,7 +61,7 @@ class IpuDoom { }; IpuDoom::IpuDoom() - : m_ipuDevice(getIpu(false, 1)), + : m_ipuDevice(getIpu(true, 1)), m_ipuGraph(/*poplar::Target::createIPUTarget(1, "ipu2")*/ m_ipuDevice.getTarget()), m_ipuEngine(nullptr) { buildIpuGraph(); @@ -67,7 +71,7 @@ IpuDoom::~IpuDoom(){}; void IpuDoom::buildIpuGraph() { m_ipuGraph.addCodelets("build/ipu_rt.gp"); - // -------- AM_Drawer_CS ------ // + // -------- GetPrintbuf_CS (helper) ------ // poplar::Tensor printbuf = m_ipuGraph.addVariable(poplar::CHAR, {(ulong)IPUPRINTBUFSIZE}, "ipuprint_buf"); @@ -80,7 +84,7 @@ void IpuDoom::buildIpuGraph() { m_ipuGraph.setTileMapping(vtx, 0); m_ipuGraph.setPerfEstimate(vtx, IPUPRINTBUFSIZE); - poplar::program::Sequence GetPrintbuf_prog({ + poplar::program::Sequence GetPrintbuf_prog({ poplar::program::Execute(GetPrintbuf_CS), poplar::program::Copy(printbuf, printbufOutStream), }); @@ -125,69 +129,20 @@ void IpuDoom::buildIpuGraph() { auto lumpNumStream = m_ipuGraph.addDeviceToHostFIFO("lumpNum-stream", poplar::INT, 1); poplar::ComputeSet P_SetupLevel_CS = m_ipuGraph.addComputeSet("P_SetupLevel_CS"); - vtx = m_ipuGraph.addVertex(P_SetupLevel_CS, "P_SetupLevel_pt0_Vertex", {{"lumpNum", m_lumpNum}}); - m_ipuGraph.setTileMapping(vtx, 0); - m_ipuGraph.setPerfEstimate(vtx, 100); - - poplar::ComputeSet P_LoadBlockMap_CS = m_ipuGraph.addComputeSet("P_LoadBlockMap_CS"); - vtx = m_ipuGraph.addVertex(P_LoadBlockMap_CS, "P_LoadBlockMap_Vertex", { + vtx = m_ipuGraph.addVertex(P_SetupLevel_CS, "P_SetupLevel_Vertex", { {"lumpNum", m_lumpNum}, {"lumpBuf", m_lumpBuf}}); m_ipuGraph.setTileMapping(vtx, 0); m_ipuGraph.setPerfEstimate(vtx, 100); - poplar::ComputeSet P_LoadVertexes_CS = m_ipuGraph.addComputeSet("P_LoadVertexes_CS"); - vtx = m_ipuGraph.addVertex(P_LoadVertexes_CS, "P_LoadVertexes_Vertex", { - {"lumpNum", m_lumpNum}, {"lumpBuf", m_lumpBuf}}); - m_ipuGraph.setTileMapping(vtx, 0); - m_ipuGraph.setPerfEstimate(vtx, 100); - - poplar::ComputeSet P_LoadSectors_CS = m_ipuGraph.addComputeSet("P_LoadSectors_CS"); - vtx = m_ipuGraph.addVertex(P_LoadSectors_CS, "P_LoadSectors_Vertex", { - {"lumpNum", m_lumpNum}, {"lumpBuf", m_lumpBuf}}); - m_ipuGraph.setTileMapping(vtx, 0); - m_ipuGraph.setPerfEstimate(vtx, 100); - - poplar::ComputeSet P_LoadSideDefs_CS = m_ipuGraph.addComputeSet("P_LoadSideDefs_CS"); - vtx = m_ipuGraph.addVertex(P_LoadSideDefs_CS, "P_LoadSideDefs_Vertex", { - {"lumpNum", m_lumpNum}, {"lumpBuf", m_lumpBuf}}); - m_ipuGraph.setTileMapping(vtx, 0); - m_ipuGraph.setPerfEstimate(vtx, 100); - - poplar::ComputeSet P_LoadLineDefs_CS = m_ipuGraph.addComputeSet("P_LoadLineDefs_CS"); - vtx = m_ipuGraph.addVertex(P_LoadLineDefs_CS, "P_LoadLineDefs_Vertex", { - {"lumpNum", m_lumpNum}, {"lumpBuf", m_lumpBuf}}); - m_ipuGraph.setTileMapping(vtx, 0); - m_ipuGraph.setPerfEstimate(vtx, 100); - - poplar::ComputeSet P_LoadSubsectors_CS = m_ipuGraph.addComputeSet("P_LoadSubsectors_CS"); - vtx = m_ipuGraph.addVertex(P_LoadSubsectors_CS, "P_LoadSubsectors_Vertex", { - {"lumpNum", m_lumpNum}, {"lumpBuf", m_lumpBuf}}); - m_ipuGraph.setTileMapping(vtx, 0); - m_ipuGraph.setPerfEstimate(vtx, 100); - - poplar::program::Sequence G_DoLoadLevel_prog({ poplar::program::Copy(miscValuesStream, m_miscValuesBuf), poplar::program::Execute(G_DoLoadLevel_CS), - poplar::program::Execute(P_SetupLevel_CS), - poplar::program::Copy(m_lumpNum, lumpNumStream), - poplar::program::Copy(lumpBufStream, m_lumpBuf), - poplar::program::Execute(P_LoadBlockMap_CS), - poplar::program::Copy(m_lumpNum, lumpNumStream), - poplar::program::Copy(lumpBufStream, m_lumpBuf), - poplar::program::Execute(P_LoadVertexes_CS), - poplar::program::Copy(m_lumpNum, lumpNumStream), - poplar::program::Copy(lumpBufStream, m_lumpBuf), - poplar::program::Execute(P_LoadSectors_CS), - poplar::program::Copy(m_lumpNum, lumpNumStream), - poplar::program::Copy(lumpBufStream, m_lumpBuf), - poplar::program::Execute(P_LoadSideDefs_CS), - poplar::program::Copy(m_lumpNum, lumpNumStream), - poplar::program::Copy(lumpBufStream, m_lumpBuf), - poplar::program::Execute(P_LoadLineDefs_CS), - poplar::program::Copy(m_lumpNum, lumpNumStream), - poplar::program::Copy(lumpBufStream, m_lumpBuf), - poplar::program::Execute(P_LoadSubsectors_CS), + poplar::program::Repeat(9, poplar::program::Sequence({ + poplar::program::Execute(P_SetupLevel_CS), + poplar::program::Copy(m_lumpNum, lumpNumStream), + poplar::program::Sync(poplar::SyncType::GLOBAL), // lumpnum must arrive before lump is loaded + poplar::program::Copy(lumpBufStream, m_lumpBuf), + })), GetPrintbuf_prog, }); @@ -241,6 +196,27 @@ void IpuDoom::buildIpuGraph() { }); + // -------- R_RenderPlayerView_CS ------ // + + + poplar::Tensor R_RenderPlayerView_MiscValsBuf = m_ipuGraph.addVariable(poplar::UNSIGNED_CHAR, {sizeof(R_RenderPlayerView_MiscValues_t)}, "R_RenderPlayerView_MiscValsBuf"); + m_ipuGraph.setTileMapping(R_RenderPlayerView_MiscValsBuf, 0); + auto R_RenderPlayerView_MiscValsBufStream = + m_ipuGraph.addHostToDeviceFIFO("R_RenderPlayerView_MiscValsBuf-stream", poplar::UNSIGNED_CHAR, sizeof(R_RenderPlayerView_MiscValues_t)); + + poplar::ComputeSet R_RenderPlayerView_CS = m_ipuGraph.addComputeSet("R_RenderPlayerView_CS"); + vtx = m_ipuGraph.addVertex(R_RenderPlayerView_CS, "R_RenderPlayerView_Vertex", + {{"frame", ipuFrame}, {"miscValues", R_RenderPlayerView_MiscValsBuf}}); + m_ipuGraph.setTileMapping(vtx, 0); + m_ipuGraph.setPerfEstimate(vtx, 10000000); + + poplar::program::Sequence R_RenderPlayerView_prog({ + poplar::program::Copy(R_RenderPlayerView_MiscValsBufStream, R_RenderPlayerView_MiscValsBuf), + poplar::program::Copy(frameInStream, ipuFrame), + poplar::program::Execute(R_RenderPlayerView_CS), + poplar::program::Copy(ipuFrame, frameOutStream), + }); + // ---------------- Final prog --------------// printf("Creating engine...\n"); @@ -251,32 +227,32 @@ void IpuDoom::buildIpuGraph() { G_Ticker_prog, G_Responder_prog, AM_Drawer_prog, + R_RenderPlayerView_prog }))); m_ipuEngine->connectStream("frame-instream", I_VideoBuffer); m_ipuEngine->connectStream("frame-outstream", I_VideoBuffer); + m_ipuEngine->connectStream("miscValues-stream", m_miscValuesBuf_h); + m_ipuEngine->connectStream("lumpNum-stream", &m_lumpNum_h); m_ipuEngine->connectStreamToCallback("printbuf-stream", [](void* p) { if (((char*)p)[0] == '\0') return; printf("[IPU] %.*s\n", IPUPRINTBUFSIZE, (char*)p); }); - - m_ipuEngine->connectStream("miscValues-stream", m_miscValuesBuf_h); - - m_ipuEngine->connectStream("lumpNum-stream", &m_lumpNum_h); m_ipuEngine->connectStreamToCallback("lumpBuf-stream", [this](void* p) { IPU_LoadLumpForTransfer(m_lumpNum_h, (byte*) p); }); - m_ipuEngine->connectStreamToCallback("marknumSpriteBuf-stream", [this](void* p) { IPU_Setup_PackMarkNums(p); }); + m_ipuEngine->connectStreamToCallback("R_RenderPlayerView_MiscValsBuf-stream", [this](void* p) { + IPU_R_RenderPlayerView_PackMiscValues(p); + }); m_ipuEngine->load(m_ipuDevice); - } - +// --- Internal interface from class IpuDoom to m_ipuEngine --- // void IpuDoom::run_IPU_Setup() { m_ipuEngine->run(0); } void IpuDoom::run_G_DoLoadLevel() { IPU_G_LoadLevel_PackMiscValues(m_miscValuesBuf_h); m_ipuEngine->run(1); } void IpuDoom::run_G_Ticker() { IPU_G_Ticker_PackMiscValues(m_miscValuesBuf_h); m_ipuEngine->run(2); } @@ -285,14 +261,19 @@ void IpuDoom::run_G_Responder(G_Responder_MiscValues_t* src_buf) { m_ipuEngine->run(3); } void IpuDoom::run_AM_Drawer() { m_ipuEngine->run(4); } +void IpuDoom::run_R_RenderPlayerView() { m_ipuEngine->run(5); } static std::unique_ptr ipuDoomInstance = nullptr; + + +// --- External interface from C to class IpuDoom --- // extern "C" { void IPU_Init() { ipuDoomInstance = std::make_unique(); ipuDoomInstance->run_IPU_Setup(); } void IPU_AM_Drawer() { ipuDoomInstance->run_AM_Drawer(); } +void IPU_R_RenderPlayerView() { ipuDoomInstance->run_R_RenderPlayerView(); } void IPU_G_DoLoadLevel() { ipuDoomInstance->run_G_DoLoadLevel(); } void IPU_G_Ticker() { ipuDoomInstance->run_G_Ticker(); } void IPU_G_Responder(G_Responder_MiscValues_t* buf) { ipuDoomInstance->run_G_Responder(buf); } diff --git a/src/ipu_host.h b/src/ipu_host.h index 0c5162c..19e9e72 100644 --- a/src/ipu_host.h +++ b/src/ipu_host.h @@ -11,6 +11,7 @@ extern "C" { void IPU_Init(void); void IPU_AM_Drawer(void); +void IPU_R_RenderPlayerView(void); void IPU_G_DoLoadLevel(void); void IPU_G_Ticker(void); diff --git a/src/ipu_transfer.c b/src/ipu_transfer.c index dd9a123..0568eca 100644 --- a/src/ipu_transfer.c +++ b/src/ipu_transfer.c @@ -81,6 +81,13 @@ void IPU_G_Responder_PackMiscValues(void* src_buf, void* dst_buf) { memcpy(dst_buf, src_buf, sizeof(G_Responder_MiscValues_t)); } +void IPU_R_RenderPlayerView_PackMiscValues(void* buf) { + R_RenderPlayerView_MiscValues_t* pack = (R_RenderPlayerView_MiscValues_t*) buf; + pack->displayplayer = displayplayer; + pack->players_displayplayer = players[displayplayer]; + pack->displayplayer_mo = *players[displayplayer].mo; +} + void IPU_Setup_PackMarkNums(void* buf) { int bufpos = 10 * sizeof(short); char namebuf[9] = "AMMNUM0\0"; diff --git a/src/ipu_transfer.h b/src/ipu_transfer.h index cda3908..82b4949 100644 --- a/src/ipu_transfer.h +++ b/src/ipu_transfer.h @@ -12,6 +12,7 @@ extern "C" { void IPU_G_LoadLevel_PackMiscValues(void* buf); void IPU_G_Ticker_PackMiscValues(void* buf); void IPU_G_Responder_PackMiscValues(void* src_buf, void* dst_buf); +void IPU_R_RenderPlayerView_PackMiscValues(void* buf); void IPU_LoadLumpForTransfer(int lumpnum, byte* buf); void IPU_Setup_PackMarkNums(void* buf); void IPU_NotifyLineMapped(line_t *line); diff --git a/src/p_mobj.c b/src/p_mobj.c index 1e36f6e..2972280 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -681,8 +681,9 @@ void P_SpawnMapThing(mapthing_t *mthing) { if (mthing->type <= 4) { // save spots for respawning in network games playerstarts[mthing->type - 1] = *mthing; - if (!deathmatch) + if (!deathmatch) { P_SpawnPlayer(mthing); + } return; } diff --git a/src/p_setup.c b/src/p_setup.c index 605cdb6..b6833d7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -429,9 +429,6 @@ void P_LoadLineDefs(int lump) { ld->backsector = 0; } - printf("[CPU] numlines: %d, sidenum0: %d, sidenum-1: %d, dx-1: %d\n", - numlines, lines[0].sidenum[1], lines[numlines-1].sidenum[1], lines[numlines-1].dx); - W_ReleaseLumpNum(lump); } diff --git a/src/r_main.c b/src/r_main.c index 22c0e0f..e4a4453 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -41,6 +41,8 @@ #include "r_things.h" #include "tables.h" +#include "ipu_host.h" + // Fineangles in the SCREENWIDTH wide window. #define FIELDOFVIEW 2048 @@ -744,6 +746,7 @@ void R_RenderPlayerView(player_t *player) { NetUpdate(); R_DrawMasked(); + IPU_R_RenderPlayerView(); // Check for new console commands. NetUpdate();