Move swrenderer into a namespace, add multithreading framework, and move drawers to commands

This commit is contained in:
Magnus Norddahl 2016-12-07 09:34:49 +01:00
parent 52645afb4b
commit 3ff91807b8
25 changed files with 5955 additions and 3472 deletions

View file

@ -883,7 +883,9 @@ set( FASTMATH_PCH_SOURCES
r_3dfloors.cpp r_3dfloors.cpp
r_bsp.cpp r_bsp.cpp
r_draw.cpp r_draw.cpp
r_drawt.cpp r_draw_pal.cpp
r_drawt_pal.cpp
r_thread.cpp
r_main.cpp r_main.cpp
r_plane.cpp r_plane.cpp
r_segs.cpp r_segs.cpp

View file

@ -15,6 +15,11 @@
#include "c_cvars.h" #include "c_cvars.h"
#include "r_3dfloors.h" #include "r_3dfloors.h"
CVAR(Int, r_3dfloors, true, 0);
namespace swrenderer
{
// external variables // external variables
int fake3D; int fake3D;
F3DFloor *fakeFloor; F3DFloor *fakeFloor;
@ -28,8 +33,6 @@ HeightLevel *height_cur = NULL;
int CurrentMirror = 0; int CurrentMirror = 0;
int CurrentSkybox = 0; int CurrentSkybox = 0;
CVAR(Int, r_3dfloors, true, 0);
// private variables // private variables
int height_max = -1; int height_max = -1;
TArray<HeightStack> toplist; TArray<HeightStack> toplist;
@ -160,3 +163,4 @@ void R_3D_LeaveSkybox()
CurrentSkybox--; CurrentSkybox--;
} }
}

View file

@ -3,6 +3,11 @@
#include "p_3dfloors.h" #include "p_3dfloors.h"
EXTERN_CVAR(Int, r_3dfloors);
namespace swrenderer
{
// special types // special types
struct HeightLevel struct HeightLevel
@ -57,7 +62,6 @@ extern HeightLevel *height_top;
extern HeightLevel *height_cur; extern HeightLevel *height_cur;
extern int CurrentMirror; extern int CurrentMirror;
extern int CurrentSkybox; extern int CurrentSkybox;
EXTERN_CVAR(Int, r_3dfloors);
// functions // functions
void R_3D_DeleteHeights(); void R_3D_DeleteHeights();
@ -67,4 +71,6 @@ void R_3D_ResetClip();
void R_3D_EnterSkybox(); void R_3D_EnterSkybox();
void R_3D_LeaveSkybox(); void R_3D_LeaveSkybox();
}
#endif #endif

View file

@ -58,6 +58,13 @@
#include "po_man.h" #include "po_man.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
CVAR (Bool, r_drawflat, false, 0) // [RH] Don't texture segs?
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
namespace swrenderer
{
using namespace drawerargs;
seg_t* curline; seg_t* curline;
side_t* sidedef; side_t* sidedef;
line_t* linedef; line_t* linedef;
@ -104,8 +111,6 @@ TArray<PortalDrawseg> WallPortals(1000); // note: this array needs to go away as
subsector_t *InSubsector; subsector_t *InSubsector;
CVAR (Bool, r_drawflat, false, 0) // [RH] Don't texture segs?
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
void R_StoreWallRange (int start, int stop); void R_StoreWallRange (int start, int stop);
@ -1396,3 +1401,5 @@ void R_RenderBSPNode (void *node)
} }
R_Subsector ((subsector_t *)((BYTE *)node - 1)); R_Subsector ((subsector_t *)((BYTE *)node - 1));
} }
}

View file

@ -27,6 +27,11 @@
#include <stddef.h> #include <stddef.h>
#include "r_defs.h" #include "r_defs.h"
EXTERN_CVAR (Bool, r_drawflat) // [RH] Don't texture segs?
namespace swrenderer
{
// The 3072 below is just an arbitrary value picked to avoid // The 3072 below is just an arbitrary value picked to avoid
// drawing lines the player is too close to that would overflow // drawing lines the player is too close to that would overflow
// the texture calculations. // the texture calculations.
@ -109,8 +114,6 @@ extern WORD MirrorFlags;
typedef void (*drawfunc_t) (int start, int stop); typedef void (*drawfunc_t) (int start, int stop);
EXTERN_CVAR (Bool, r_drawflat) // [RH] Don't texture segs?
// BSP? // BSP?
void R_ClearClipSegs (short left, short right); void R_ClearClipSegs (short left, short right);
void R_ClearDrawSegs (); void R_ClearDrawSegs ();
@ -119,5 +122,6 @@ void R_RenderBSPNode (void *node);
// killough 4/13/98: fake floors/ceilings for deep water / fake ceilings: // killough 4/13/98: fake floors/ceilings for deep water / fake ceilings:
sector_t *R_FakeFlat(sector_t *, sector_t *, int *, int *, bool); sector_t *R_FakeFlat(sector_t *, sector_t *, int *, int *, bool);
}
#endif #endif

View file

@ -55,7 +55,7 @@ enum
SIL_BOTH SIL_BOTH
}; };
extern size_t MaxDrawSegs; namespace swrenderer { extern size_t MaxDrawSegs; }
struct FDisplacement; struct FDisplacement;
// //

File diff suppressed because it is too large Load diff

View file

@ -1,287 +1,208 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// DESCRIPTION:
// System specific interface stuff.
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef __R_DRAW__
#define __R_DRAW__
#include "r_defs.h" #include "r_defs.h"
extern "C" int ylookup[MAXHEIGHT]; EXTERN_CVAR(Bool, r_multithreaded);
EXTERN_CVAR(Int, r_drawfuzz);
EXTERN_CVAR(Bool, r_drawtrans);
EXTERN_CVAR(Float, transsouls);
EXTERN_CVAR(Int, r_columnmethod);
extern "C" int dc_pitch; // [RH] Distance between rows namespace swrenderer
extern "C" lighttable_t*dc_colormap;
extern "C" int dc_x;
extern "C" int dc_yl;
extern "C" int dc_yh;
extern "C" fixed_t dc_iscale;
extern double dc_texturemid;
extern "C" fixed_t dc_texturefrac;
extern "C" int dc_color; // [RH] For flat colors (no texturing)
extern "C" DWORD dc_srccolor;
extern "C" DWORD *dc_srcblend;
extern "C" DWORD *dc_destblend;
// first pixel in a column
extern "C" const BYTE* dc_source;
extern "C" BYTE *dc_dest, *dc_destorg;
extern "C" int dc_count;
extern "C" DWORD vplce[4];
extern "C" DWORD vince[4];
extern "C" BYTE* palookupoffse[4];
extern "C" const BYTE* bufplce[4];
extern "C" const BYTE* bufplce2[4];
extern "C" uint32_t bufheight[4];
// [RH] Temporary buffer for column drawing
extern "C" BYTE *dc_temp;
extern "C" unsigned int dc_tspans[4][MAXHEIGHT];
extern "C" unsigned int *dc_ctspan[4];
extern "C" unsigned int horizspans[4];
// [RH] Pointers to the different column and span drawers...
// The span blitting interface.
// Hook in assembler or system specific BLT here.
extern DWORD (*dovline1) ();
extern DWORD (*doprevline1) ();
#ifdef X64_ASM
#define dovline4 vlinetallasm4
extern "C" void vlinetallasm4();
#else
extern void (*dovline4) ();
#endif
extern void setupvline (int);
extern DWORD (*domvline1) ();
extern void (*domvline4) ();
extern void setupmvline (int);
extern void setuptmvline (int);
// The Spectre/Invisibility effect.
extern void R_DrawFuzzColumn(void);
// [RH] Draw shaded column
extern void (*R_DrawShadedColumn)(void);
// Draw with color translation tables, for player sprite rendering,
// Green/Red/Blue/Indigo shirts.
extern void (*R_DrawTranslatedColumn)(void);
// Span drawing for rows, floor/ceiling. No Spectre effect needed.
extern void (*R_DrawSpan)(void);
void R_SetupSpanBits(FTexture *tex);
void R_SetSpanColormap(BYTE *colormap);
void R_SetSpanSource(const BYTE *pixels);
// Span drawing for masked textures.
extern void (*R_DrawSpanMasked)(void);
// Span drawing for translucent textures.
void R_DrawSpanTranslucent(void);
// Span drawing for masked, translucent textures.
void R_DrawSpanMaskedTranslucent(void);
// Span drawing for translucent, additive textures.
void R_DrawSpanAddClamp(void);
// Span drawing for masked, translucent, additive textures.
void R_DrawSpanMaskedAddClamp(void);
// [RH] Span blit into an interleaved intermediate buffer
extern void (*R_DrawColumnHoriz)(void);
// [RH] Initialize the above pointers
void R_InitColumnDrawers ();
// [RH] Moves data from the temporary buffer to the screen.
void rt_copy1col(int hx, int sx, int yl, int yh);
void rt_copy4cols(int sx, int yl, int yh);
void rt_map4cols(int sx, int yl, int yh);
extern "C"
{ {
struct vissprite_t;
void rt_shaded1col (int hx, int sx, int yl, int yh); extern double dc_texturemid;
void rt_shaded4cols_c (int sx, int yl, int yh);
void rt_shaded4cols_asm (int sx, int yl, int yh);
void rt_map1col (int hx, int sx, int yl, int yh); namespace drawerargs
void rt_add1col (int hx, int sx, int yl, int yh); {
void rt_addclamp1col (int hx, int sx, int yl, int yh); extern int dc_pitch;
void rt_subclamp1col (int hx, int sx, int yl, int yh); extern lighttable_t *dc_colormap;
void rt_revsubclamp1col (int hx, int sx, int yl, int yh); extern int dc_x;
extern int dc_yl;
extern int dc_yh;
extern fixed_t dc_iscale;
extern fixed_t dc_texturefrac;
extern uint32_t dc_textureheight;
extern int dc_color;
extern uint32_t dc_srccolor;
extern uint32_t dc_srccolor_bgra;
extern uint32_t *dc_srcblend;
extern uint32_t *dc_destblend;
extern fixed_t dc_srcalpha;
extern fixed_t dc_destalpha;
extern const uint8_t *dc_source;
extern const uint8_t *dc_source2;
extern uint32_t dc_texturefracx;
extern uint8_t *dc_translation;
extern uint8_t *dc_dest;
extern uint8_t *dc_destorg;
extern int dc_destheight;
extern int dc_count;
void rt_tlate1col (int hx, int sx, int yl, int yh); extern uint32_t vplce[4];
void rt_tlateadd1col (int hx, int sx, int yl, int yh); extern uint32_t vince[4];
void rt_tlateaddclamp1col (int hx, int sx, int yl, int yh); extern uint8_t *palookupoffse[4];
void rt_tlatesubclamp1col (int hx, int sx, int yl, int yh); extern fixed_t palookuplight[4];
void rt_tlaterevsubclamp1col (int hx, int sx, int yl, int yh); extern const uint8_t *bufplce[4];
extern const uint8_t *bufplce2[4];
extern uint32_t buftexturefracx[4];
extern uint32_t bufheight[4];
extern int vlinebits;
extern int mvlinebits;
extern int tmvlinebits;
void rt_add4cols_c (int sx, int yl, int yh); extern int ds_y;
void rt_addclamp4cols_c (int sx, int yl, int yh); extern int ds_x1;
void rt_subclamp4cols (int sx, int yl, int yh); extern int ds_x2;
void rt_revsubclamp4cols (int sx, int yl, int yh); extern lighttable_t * ds_colormap;
extern dsfixed_t ds_light;
extern dsfixed_t ds_xfrac;
extern dsfixed_t ds_yfrac;
extern dsfixed_t ds_xstep;
extern dsfixed_t ds_ystep;
extern int ds_xbits;
extern int ds_ybits;
extern fixed_t ds_alpha;
extern double ds_lod;
extern const uint8_t *ds_source;
extern int ds_color;
void rt_tlate4cols (int sx, int yl, int yh); extern unsigned int dc_tspans[4][MAXHEIGHT];
void rt_tlateadd4cols (int sx, int yl, int yh); extern unsigned int *dc_ctspan[4];
void rt_tlateaddclamp4cols (int sx, int yl, int yh); extern unsigned int *horizspan[4];
void rt_tlatesubclamp4cols (int sx, int yl, int yh); }
void rt_tlaterevsubclamp4cols (int sx, int yl, int yh);
void rt_add4cols_asm (int sx, int yl, int yh); extern int ylookup[MAXHEIGHT];
void rt_addclamp4cols_asm (int sx, int yl, int yh); extern uint8_t shadetables[/*NUMCOLORMAPS*16*256*/];
extern FDynamicColormap ShadeFakeColormap[16];
extern uint8_t identitymap[256];
extern FDynamicColormap identitycolormap;
// Spectre/Invisibility.
#define FUZZTABLE 50
extern int fuzzoffset[FUZZTABLE + 1];
extern int fuzzpos;
extern int fuzzviewheight;
void R_InitColumnDrawers();
void R_InitShadeMaps();
void R_InitFuzzTable(int fuzzoff);
enum ESPSResult
{
DontDraw, // not useful to draw this
DoDraw0, // draw this as if r_columnmethod is 0
DoDraw1, // draw this as if r_columnmethod is 1
};
ESPSResult R_SetPatchStyle(FRenderStyle style, fixed_t alpha, int translation, uint32_t color);
ESPSResult R_SetPatchStyle(FRenderStyle style, float alpha, int translation, uint32_t color);
void R_FinishSetPatchStyle(); // Call this after finished drawing the current thing, in case its style was STYLE_Shade
bool R_GetTransMaskDrawers(fixed_t(**tmvline1)(), void(**tmvline4)());
const uint8_t *R_GetColumn(FTexture *tex, int col);
void wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const uint8_t *(*getcol)(FTexture *tex, int col) = R_GetColumn);
void maskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const uint8_t *(*getcol)(FTexture *tex, int col) = R_GetColumn);
void transmaskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const uint8_t *(*getcol)(FTexture *tex, int col) = R_GetColumn);
void rt_initcols(uint8_t *buffer = nullptr);
void rt_span_coverage(int x, int start, int stop);
void rt_draw4cols(int sx);
void rt_flip_posts();
void rt_copy1col(int hx, int sx, int yl, int yh);
void rt_copy4cols(int sx, int yl, int yh);
void rt_shaded1col(int hx, int sx, int yl, int yh);
void rt_shaded4cols(int sx, int yl, int yh);
void rt_map1col(int hx, int sx, int yl, int yh);
void rt_add1col(int hx, int sx, int yl, int yh);
void rt_addclamp1col(int hx, int sx, int yl, int yh);
void rt_subclamp1col(int hx, int sx, int yl, int yh);
void rt_revsubclamp1col(int hx, int sx, int yl, int yh);
void rt_tlate1col(int hx, int sx, int yl, int yh);
void rt_tlateadd1col(int hx, int sx, int yl, int yh);
void rt_tlateaddclamp1col(int hx, int sx, int yl, int yh);
void rt_tlatesubclamp1col(int hx, int sx, int yl, int yh);
void rt_tlaterevsubclamp1col(int hx, int sx, int yl, int yh);
void rt_map4cols(int sx, int yl, int yh);
void rt_add4cols(int sx, int yl, int yh);
void rt_addclamp4cols(int sx, int yl, int yh);
void rt_subclamp4cols(int sx, int yl, int yh);
void rt_revsubclamp4cols(int sx, int yl, int yh);
void rt_tlate4cols(int sx, int yl, int yh);
void rt_tlateadd4cols(int sx, int yl, int yh);
void rt_tlateaddclamp4cols(int sx, int yl, int yh);
void rt_tlatesubclamp4cols(int sx, int yl, int yh);
void rt_tlaterevsubclamp4cols(int sx, int yl, int yh);
void R_DrawColumnHoriz();
void R_DrawColumn();
void R_DrawFuzzColumn();
void R_DrawTranslatedColumn();
void R_DrawShadedColumn();
void R_FillColumn();
void R_FillAddColumn();
void R_FillAddClampColumn();
void R_FillSubClampColumn();
void R_FillRevSubClampColumn();
void R_DrawAddColumn();
void R_DrawTlatedAddColumn();
void R_DrawAddClampColumn();
void R_DrawAddClampTranslatedColumn();
void R_DrawSubClampColumn();
void R_DrawSubClampTranslatedColumn();
void R_DrawRevSubClampColumn();
void R_DrawRevSubClampTranslatedColumn();
void R_DrawSpan();
void R_DrawSpanMasked();
void R_DrawSpanTranslucent();
void R_DrawSpanMaskedTranslucent();
void R_DrawSpanAddClamp();
void R_DrawSpanMaskedAddClamp();
void R_FillSpan();
void R_DrawTiltedSpan(int y, int x1, int x2, const FVector3 &plane_sz, const FVector3 &plane_su, const FVector3 &plane_sv, bool plane_shade, int planeshade, float planelightfloat, fixed_t pviewx, fixed_t pviewy);
void R_DrawColoredSpan(int y, int x1, int x2);
void R_SetupDrawSlab(uint8_t *colormap);
void R_DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const uint8_t *vptr, uint8_t *p);
void R_DrawFogBoundary(int x1, int x2, short *uclip, short *dclip);
uint32_t vlinec1();
void vlinec4();
uint32_t mvlinec1();
void mvlinec4();
fixed_t tmvline1_add();
void tmvline4_add();
fixed_t tmvline1_addclamp();
void tmvline4_addclamp();
fixed_t tmvline1_subclamp();
void tmvline4_subclamp();
fixed_t tmvline1_revsubclamp();
void tmvline4_revsubclamp();
void R_FillColumnHoriz();
void R_FillSpan();
inline uint32_t dovline1() { return vlinec1(); }
inline void dovline4() { vlinec4(); }
inline uint32_t domvline1() { return mvlinec1(); }
inline void domvline4() { mvlinec4(); }
void setupvline(int fracbits);
void setupmvline(int fracbits);
void setuptmvline(int fracbits);
void R_DrawSingleSkyCol1(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawSingleSkyCol4(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawDoubleSkyCol1(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawDoubleSkyCol4(uint32_t solid_top, uint32_t solid_bottom);
void R_SetColorMapLight(lighttable_t *base_colormap, float light, int shade);
void R_SetDSColorMapLight(lighttable_t *base_colormap, float light, int shade);
void R_SetTranslationMap(lighttable_t *translation);
void R_SetupSpanBits(FTexture *tex);
void R_SetSpanColormap(lighttable_t *colormap);
void R_SetSpanSource(FTexture *tex);
void R_MapTiltedPlane(int y, int x1);
void R_MapColoredPlane(int y, int x1);
void R_DrawParticle(vissprite_t *);
} }
#ifdef X86_ASM
#define rt_shaded4cols rt_shaded4cols_asm
#define rt_add4cols rt_add4cols_asm
#define rt_addclamp4cols rt_addclamp4cols_asm
#else
#define rt_shaded4cols rt_shaded4cols_c
#define rt_add4cols rt_add4cols_c
#define rt_addclamp4cols rt_addclamp4cols_c
#endif
void rt_flip_posts();
void rt_draw4cols (int sx);
// [RH] Preps the temporary horizontal buffer.
void rt_initcols (BYTE *buffer=NULL);
void R_DrawFogBoundary (int x1, int x2, short *uclip, short *dclip);
#ifdef X86_ASM
void R_DrawShadedColumnP_C (void);
extern "C" void R_DrawSpanP_ASM (void);
extern "C" void R_DrawSpanMaskedP_ASM (void);
void R_DrawColumnHorizP_C(void);
#else
void R_DrawShadedColumnP_C (void);
void R_DrawSpanP_C (void);
void R_DrawSpanMaskedP_C (void);
#endif
void R_DrawColumn();
void R_DrawColumnHorizP_C(void);
void R_DrawTranslatedColumnP_C(void);
void R_DrawSpanTranslucent (void);
void R_DrawSpanMaskedTranslucent (void);
void R_DrawTlatedLucentColumnP_C (void);
#define R_DrawTlatedLucentColumn R_DrawTlatedLucentColumnP_C
void R_FillColumnP (void);
void R_FillColumnHorizP (void);
void R_FillSpan (void);
#ifdef X86_ASM
#define R_SetupDrawSlab R_SetupDrawSlabA
#define R_DrawSlab R_DrawSlabA
#else
#define R_SetupDrawSlab R_SetupDrawSlabC
#define R_DrawSlab R_DrawSlabC
#endif
extern "C" void R_SetupDrawSlab(const BYTE *colormap);
extern "C" void R_DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *vptr, BYTE *p);
extern "C" int ds_y;
extern "C" int ds_x1;
extern "C" int ds_x2;
extern "C" lighttable_t* ds_colormap;
extern "C" dsfixed_t ds_xfrac;
extern "C" dsfixed_t ds_yfrac;
extern "C" dsfixed_t ds_xstep;
extern "C" dsfixed_t ds_ystep;
extern "C" int ds_xbits;
extern "C" int ds_ybits;
extern "C" fixed_t ds_alpha;
// start of a 64*64 tile image
extern "C" const BYTE* ds_source;
extern "C" int ds_color; // [RH] For flat color (no texturing)
extern BYTE shadetables[/*NUMCOLORMAPS*16*256*/];
extern FDynamicColormap ShadeFakeColormap[16];
extern BYTE identitymap[256];
extern BYTE *dc_translation;
// [RH] Added for muliresolution support
void R_InitShadeMaps();
void R_InitFuzzTable (int fuzzoff);
// [RH] Consolidate column drawer selection
enum ESPSResult
{
DontDraw, // not useful to draw this
DoDraw0, // draw this as if r_columnmethod is 0
DoDraw1, // draw this as if r_columnmethod is 1
};
ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation, DWORD color);
inline ESPSResult R_SetPatchStyle(FRenderStyle style, float alpha, int translation, DWORD color)
{
return R_SetPatchStyle(style, FLOAT2FIXED(alpha), translation, color);
}
// Call this after finished drawing the current thing, in case its
// style was STYLE_Shade
void R_FinishSetPatchStyle ();
// transmaskwallscan calls this to find out what column drawers to use
bool R_GetTransMaskDrawers (fixed_t (**tmvline1)(), void (**tmvline4)());
// Retrieve column data for wallscan. Should probably be removed
// to just use the texture's GetColumn() method. It just exists
// for double-layer skies.
const BYTE *R_GetColumn (FTexture *tex, int col);
void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
// maskwallscan is exactly like wallscan but does not draw anything where the texture is color 0.
void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
// transmaskwallscan is like maskwallscan, but it can also blend to the background
void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
void R_DrawSingleSkyCol1(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawSingleSkyCol4(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawDoubleSkyCol1(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawDoubleSkyCol4(uint32_t solid_top, uint32_t solid_bottom);
#endif

2593
src/r_draw_pal.cpp Normal file

File diff suppressed because it is too large Load diff

333
src/r_draw_pal.h Normal file
View file

@ -0,0 +1,333 @@
#pragma once
#include "r_draw.h"
#include "v_palette.h"
#include "r_thread.h"
namespace swrenderer
{
class PalWall1Command : public DrawerCommand
{
public:
PalWall1Command();
FString DebugInfo() override { return "PalWallCommand"; }
protected:
uint32_t _iscale;
uint32_t _texturefrac;
uint8_t *_colormap;
int _count;
const uint8_t *_source;
uint8_t *_dest;
int _vlinebits;
int _mvlinebits;
int _tmvlinebits;
int _pitch;
uint32_t *_srcblend;
uint32_t *_destblend;
};
class PalWall4Command : public DrawerCommand
{
public:
PalWall4Command();
FString DebugInfo() override { return "PalWallCommand"; }
protected:
uint8_t *_dest;
int _count;
int _pitch;
int _vlinebits;
int _mvlinebits;
int _tmvlinebits;
uint8_t *_palookupoffse[4];
const uint8_t *_bufplce[4];
uint32_t _vince[4];
uint32_t _vplce[4];
uint32_t *_srcblend;
uint32_t *_destblend;
};
class DrawWall1PalCommand : public PalWall1Command { public: void Execute(DrawerThread *thread) override; };
class DrawWall4PalCommand : public PalWall4Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallMasked1PalCommand : public PalWall1Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallMasked4PalCommand : public PalWall4Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallAdd1PalCommand : public PalWall1Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallAdd4PalCommand : public PalWall4Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallAddClamp1PalCommand : public PalWall1Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallAddClamp4PalCommand : public PalWall4Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallSubClamp1PalCommand : public PalWall1Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallSubClamp4PalCommand : public PalWall4Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallRevSubClamp1PalCommand : public PalWall1Command { public: void Execute(DrawerThread *thread) override; };
class DrawWallRevSubClamp4PalCommand : public PalWall4Command { public: void Execute(DrawerThread *thread) override; };
class PalSkyCommand : public DrawerCommand
{
public:
PalSkyCommand(uint32_t solid_top, uint32_t solid_bottom);
FString DebugInfo() override { return "PalSkyCommand"; }
protected:
uint32_t solid_top;
uint32_t solid_bottom;
uint8_t *_dest;
int _count;
int _pitch;
const uint8_t *_bufplce[4];
const uint8_t *_bufplce2[4];
int _bufheight[4];
uint32_t _vince[4];
uint32_t _vplce[4];
};
class DrawSingleSky1PalCommand : public PalSkyCommand { public: using PalSkyCommand::PalSkyCommand; void Execute(DrawerThread *thread) override; };
class DrawSingleSky4PalCommand : public PalSkyCommand { public: using PalSkyCommand::PalSkyCommand; void Execute(DrawerThread *thread) override; };
class DrawDoubleSky1PalCommand : public PalSkyCommand { public: using PalSkyCommand::PalSkyCommand; void Execute(DrawerThread *thread) override; };
class DrawDoubleSky4PalCommand : public PalSkyCommand { public: using PalSkyCommand::PalSkyCommand; void Execute(DrawerThread *thread) override; };
class PalColumnCommand : public DrawerCommand
{
public:
PalColumnCommand();
FString DebugInfo() override { return "PalColumnCommand"; }
protected:
int _count;
uint8_t *_dest;
int _pitch;
fixed_t _iscale;
fixed_t _texturefrac;
const uint8_t *_colormap;
const uint8_t *_source;
const uint8_t *_translation;
int _color;
uint32_t *_srcblend;
uint32_t *_destblend;
uint32_t _srccolor;
};
class DrawColumnPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class FillColumnPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class FillColumnAddPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class FillColumnAddClampPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class FillColumnSubClampPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class FillColumnRevSubClampPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnAddPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnTranslatedPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnTlatedAddPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnShadedPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnAddClampPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnAddClampTranslatedPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnSubClampPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnSubClampTranslatedPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnRevSubClampPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawColumnRevSubClampTranslatedPalCommand : public PalColumnCommand { public: void Execute(DrawerThread *thread) override; };
class DrawFuzzColumnPalCommand : public DrawerCommand
{
public:
DrawFuzzColumnPalCommand();
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "DrawFuzzColumnPalCommand"; }
private:
int _yl;
int _yh;
int _x;
uint8_t *_destorg;
int _pitch;
int _fuzzpos;
int _fuzzviewheight;
};
class PalSpanCommand : public DrawerCommand
{
public:
PalSpanCommand();
FString DebugInfo() override { return "PalSpanCommand"; }
protected:
const uint8_t *_source;
const uint8_t *_colormap;
dsfixed_t _xfrac;
dsfixed_t _yfrac;
int _y;
int _x1;
int _x2;
uint8_t *_destorg;
dsfixed_t _xstep;
dsfixed_t _ystep;
int _xbits;
int _ybits;
uint32_t *_srcblend;
uint32_t *_destblend;
int _color;
};
class DrawSpanPalCommand : public PalSpanCommand { public: void Execute(DrawerThread *thread) override; };
class DrawSpanMaskedPalCommand : public PalSpanCommand { public: void Execute(DrawerThread *thread) override; };
class DrawSpanTranslucentPalCommand : public PalSpanCommand { public: void Execute(DrawerThread *thread) override; };
class DrawSpanMaskedTranslucentPalCommand : public PalSpanCommand { public: void Execute(DrawerThread *thread) override; };
class DrawSpanAddClampPalCommand : public PalSpanCommand { public: void Execute(DrawerThread *thread) override; };
class DrawSpanMaskedAddClampPalCommand : public PalSpanCommand { public: void Execute(DrawerThread *thread) override; };
class FillSpanPalCommand : public PalSpanCommand { public: void Execute(DrawerThread *thread) override; };
class DrawTiltedSpanPalCommand : public DrawerCommand
{
public:
DrawTiltedSpanPalCommand(int y, int x1, int x2, const FVector3 &plane_sz, const FVector3 &plane_su, const FVector3 &plane_sv, bool plane_shade, int planeshade, float planelightfloat, fixed_t pviewx, fixed_t pviewy);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "DrawTiltedSpanPalCommand"; }
private:
void CalcTiltedLighting(double lval, double lend, int width, DrawerThread *thread);
int y;
int x1;
int x2;
FVector3 plane_sz;
FVector3 plane_su;
FVector3 plane_sv;
bool plane_shade;
int planeshade;
float planelightfloat;
fixed_t pviewx;
fixed_t pviewy;
const uint8_t *_colormap;
uint8_t *_destorg;
int _ybits;
int _xbits;
const uint8_t *_source;
uint8_t *basecolormapdata;
};
class DrawColoredSpanPalCommand : public PalSpanCommand
{
public:
DrawColoredSpanPalCommand(int y, int x1, int x2);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "DrawColoredSpanPalCommand"; }
private:
int y;
int x1;
int x2;
int color;
uint8_t *destorg;
};
class DrawSlabPalCommand : public PalSpanCommand
{
public:
DrawSlabPalCommand(int dx, fixed_t v, int dy, fixed_t vi, const uint8_t *vptr, uint8_t *p, const uint8_t *colormap);
void Execute(DrawerThread *thread) override;
private:
int _dx;
fixed_t _v;
int _dy;
fixed_t _vi;
const uint8_t *_vptr;
uint8_t *_p;
const uint8_t *_colormap;
int _pitch;
int _start_y;
};
class DrawFogBoundaryLinePalCommand : public PalSpanCommand
{
public:
DrawFogBoundaryLinePalCommand(int y, int x1, int x2);
void Execute(DrawerThread *thread) override;
private:
int y, x1, x2;
const uint8_t *_colormap;
uint8_t *_destorg;
};
class RtInitColsPalCommand : public DrawerCommand
{
public:
RtInitColsPalCommand(uint8_t *buff);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "RtInitColsPalCommand"; }
private:
uint8_t *buff;
};
class PalColumnHorizCommand : public DrawerCommand
{
public:
PalColumnHorizCommand();
protected:
const uint8_t *_source;
fixed_t _iscale;
fixed_t _texturefrac;
int _count;
int _color;
int _x;
int _yl;
};
class DrawColumnHorizPalCommand : public PalColumnHorizCommand
{
public:
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "DrawColumnHorizPalCommand"; }
};
class FillColumnHorizPalCommand : public PalColumnHorizCommand
{
public:
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "FillColumnHorizPalCommand"; }
};
class PalRtCommand : public DrawerCommand
{
public:
PalRtCommand(int hx, int sx, int yl, int yh);
FString DebugInfo() override { return "PalRtCommand"; }
protected:
int hx, sx, yl, yh;
uint8_t *_destorg;
int _pitch;
const uint8_t *_colormap;
const uint32_t *_srcblend;
const uint32_t *_destblend;
const uint8_t *_translation;
int _color;
};
class DrawColumnRt1CopyPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt4CopyPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt1PalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt4PalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt1TranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt4TranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt1AddPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt4AddPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
//class DrawColumnRt1AddTranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
//class DrawColumnRt4AddTranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt1ShadedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt4ShadedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt1AddClampPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt4AddClampPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
//class DrawColumnRt1AddClampTranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
//class DrawColumnRt4AddClampTranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt1SubClampPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt4SubClampPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
//class DrawColumnRt1SubClampTranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
//class DrawColumnRt4SubClampTranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt1RevSubClampPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
class DrawColumnRt4RevSubClampPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
//class DrawColumnRt1RevSubClampTranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
//class DrawColumnRt4RevSubClampTranslatedPalCommand : public PalRtCommand { public: using PalRtCommand::PalRtCommand; void Execute(DrawerThread *thread) override; };
}

867
src/r_drawt_pal.cpp Normal file
View file

@ -0,0 +1,867 @@
/*
** r_drawt.cpp
** Faster column drawers for modern processors
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
** These functions stretch columns into a temporary buffer and then
** map them to the screen. On modern machines, this is faster than drawing
** them directly to the screen.
**
** Will I be able to even understand any of this if I come back to it later?
** Let's hope so. :-)
*/
#include "templates.h"
#include "doomtype.h"
#include "doomdef.h"
#include "r_defs.h"
#include "r_draw.h"
#include "r_main.h"
#include "r_things.h"
#include "v_video.h"
#include "r_draw_pal.h"
// I should have commented this stuff better.
//
// dc_temp is the buffer R_DrawColumnHoriz writes into.
// dc_tspans points into it.
// dc_ctspan points into dc_tspans.
// horizspan also points into dc_tspans.
// dc_ctspan is advanced while drawing into dc_temp.
// horizspan is advanced up to dc_ctspan when drawing from dc_temp to the screen.
namespace swrenderer
{
RtInitColsPalCommand::RtInitColsPalCommand(uint8_t *buff) : buff(buff)
{
}
void RtInitColsPalCommand::Execute(DrawerThread *thread)
{
thread->dc_temp = buff == nullptr ? thread->dc_temp_buff : buff;
}
/////////////////////////////////////////////////////////////////////
PalColumnHorizCommand::PalColumnHorizCommand()
{
using namespace drawerargs;
_source = dc_source;
_iscale = dc_iscale;
_texturefrac = dc_texturefrac;
_count = dc_count;
_color = dc_color;
_x = dc_x;
_yl = dc_yl;
}
void DrawColumnHorizPalCommand::Execute(DrawerThread *thread)
{
int count = _count;
uint8_t *dest;
fixed_t fracstep;
fixed_t frac;
count = thread->count_for_thread(_yl, count);
if (count <= 0)
return;
fracstep = _iscale;
frac = _texturefrac;
const uint8_t *source = _source;
int x = _x & 3;
dest = &thread->dc_temp[x + thread->temp_line_for_thread(_yl) * 4];
frac += fracstep * thread->skipped_by_thread(_yl);
fracstep *= thread->num_cores;
if (count & 1) {
*dest = source[frac >> FRACBITS]; dest += 4; frac += fracstep;
}
if (count & 2) {
dest[0] = source[frac >> FRACBITS]; frac += fracstep;
dest[4] = source[frac >> FRACBITS]; frac += fracstep;
dest += 8;
}
if (count & 4) {
dest[0] = source[frac >> FRACBITS]; frac += fracstep;
dest[4] = source[frac >> FRACBITS]; frac += fracstep;
dest[8] = source[frac >> FRACBITS]; frac += fracstep;
dest[12] = source[frac >> FRACBITS]; frac += fracstep;
dest += 16;
}
count >>= 3;
if (!count) return;
do
{
dest[0] = source[frac >> FRACBITS]; frac += fracstep;
dest[4] = source[frac >> FRACBITS]; frac += fracstep;
dest[8] = source[frac >> FRACBITS]; frac += fracstep;
dest[12] = source[frac >> FRACBITS]; frac += fracstep;
dest[16] = source[frac >> FRACBITS]; frac += fracstep;
dest[20] = source[frac >> FRACBITS]; frac += fracstep;
dest[24] = source[frac >> FRACBITS]; frac += fracstep;
dest[28] = source[frac >> FRACBITS]; frac += fracstep;
dest += 32;
} while (--count);
}
void FillColumnHorizPalCommand::Execute(DrawerThread *thread)
{
int count = _count;
uint8_t color = _color;
uint8_t *dest;
count = thread->count_for_thread(_yl, count);
if (count <= 0)
return;
int x = _x & 3;
dest = &thread->dc_temp[x + thread->temp_line_for_thread(_yl) * 4];
if (count & 1) {
*dest = color;
dest += 4;
}
if (!(count >>= 1))
return;
do {
dest[0] = color; dest[4] = color;
dest += 8;
} while (--count);
}
/////////////////////////////////////////////////////////////////////
PalRtCommand::PalRtCommand(int hx, int sx, int yl, int yh) : hx(hx), sx(sx), yl(yl), yh(yh)
{
using namespace drawerargs;
_destorg = dc_destorg;
_pitch = dc_pitch;
_colormap = dc_colormap;
_srcblend = dc_srcblend;
_destblend = dc_destblend;
_translation = dc_translation;
_color = dc_color;
}
void DrawColumnRt1CopyPalCommand::Execute(DrawerThread *thread)
{
uint8_t *source;
uint8_t *dest;
int count;
int pitch;
count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4 + hx];
pitch = _pitch * thread->num_cores;
if (count & 1) {
*dest = *source;
source += 4;
dest += pitch;
}
if (count & 2) {
dest[0] = source[0];
dest[pitch] = source[4];
source += 8;
dest += pitch*2;
}
if (!(count >>= 2))
return;
do {
dest[0] = source[0];
dest[pitch] = source[4];
dest[pitch*2] = source[8];
dest[pitch*3] = source[12];
source += 16;
dest += pitch*4;
} while (--count);
}
void DrawColumnRt4CopyPalCommand::Execute(DrawerThread *thread)
{
int *source;
int *dest;
int count;
int pitch;
count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
dest = (int *)(ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg);
source = (int *)(&thread->dc_temp[thread->temp_line_for_thread(yl)*4]);
pitch = _pitch*thread->num_cores/sizeof(int);
if (count & 1) {
*dest = *source;
source += 4/sizeof(int);
dest += pitch;
}
if (!(count >>= 1))
return;
do {
dest[0] = source[0];
dest[pitch] = source[4/sizeof(int)];
source += 8/sizeof(int);
dest += pitch*2;
} while (--count);
}
void DrawColumnRt1PalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int count;
int pitch;
count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
colormap = _colormap;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl) *4 + hx];
pitch = _pitch*thread->num_cores;
if (count & 1) {
*dest = colormap[*source];
source += 4;
dest += pitch;
}
if (!(count >>= 1))
return;
do {
dest[0] = colormap[source[0]];
dest[pitch] = colormap[source[4]];
source += 8;
dest += pitch*2;
} while (--count);
}
void DrawColumnRt4PalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int count;
int pitch;
count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
colormap = _colormap;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4];
pitch = _pitch*thread->num_cores;
if (count & 1) {
dest[0] = colormap[source[0]];
dest[1] = colormap[source[1]];
dest[2] = colormap[source[2]];
dest[3] = colormap[source[3]];
source += 4;
dest += pitch;
}
if (!(count >>= 1))
return;
do {
dest[0] = colormap[source[0]];
dest[1] = colormap[source[1]];
dest[2] = colormap[source[2]];
dest[3] = colormap[source[3]];
dest[pitch] = colormap[source[4]];
dest[pitch+1] = colormap[source[5]];
dest[pitch+2] = colormap[source[6]];
dest[pitch+3] = colormap[source[7]];
source += 8;
dest += pitch*2;
} while (--count);
}
void DrawColumnRt1TranslatedPalCommand::Execute(DrawerThread *thread)
{
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
uint8_t *source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4 + hx];
const uint8_t *translation = _translation;
// Things we do to hit the compiler's optimizer with a clue bat:
// 1. Parallelism is explicitly spelled out by using a separate
// C instruction for each assembly instruction. GCC lets me
// have four temporaries, but VC++ spills to the stack with
// more than two. Two is probably optimal, anyway.
// 2. The results of the translation lookups are explicitly
// stored in byte-sized variables. This causes the VC++ code
// to use byte mov instructions in most cases; for apparently
// random reasons, it will use movzx for some places. GCC
// ignores this and uses movzx always.
// Do 8 rows at a time.
for (int count8 = count >> 3; count8; --count8)
{
int c0, c1;
uint8_t b0, b1;
c0 = source[0]; c1 = source[4];
b0 = translation[c0]; b1 = translation[c1];
source[0] = b0; source[4] = b1;
c0 = source[8]; c1 = source[12];
b0 = translation[c0]; b1 = translation[c1];
source[8] = b0; source[12] = b1;
c0 = source[16]; c1 = source[20];
b0 = translation[c0]; b1 = translation[c1];
source[16] = b0; source[20] = b1;
c0 = source[24]; c1 = source[28];
b0 = translation[c0]; b1 = translation[c1];
source[24] = b0; source[28] = b1;
source += 32;
}
// Finish by doing 1 row at a time.
for (count &= 7; count; --count, source += 4)
{
source[0] = translation[source[0]];
}
}
void DrawColumnRt4TranslatedPalCommand::Execute(DrawerThread *thread)
{
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
uint8_t *source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4];
const uint8_t *translation = _translation;
int c0, c1;
uint8_t b0, b1;
// Do 2 rows at a time.
for (int count8 = count >> 1; count8; --count8)
{
c0 = source[0]; c1 = source[1];
b0 = translation[c0]; b1 = translation[c1];
source[0] = b0; source[1] = b1;
c0 = source[2]; c1 = source[3];
b0 = translation[c0]; b1 = translation[c1];
source[2] = b0; source[3] = b1;
c0 = source[4]; c1 = source[5];
b0 = translation[c0]; b1 = translation[c1];
source[4] = b0; source[5] = b1;
c0 = source[6]; c1 = source[7];
b0 = translation[c0]; b1 = translation[c1];
source[6] = b0; source[7] = b1;
source += 8;
}
// Do the final row if count was odd.
if (count & 1)
{
c0 = source[0]; c1 = source[1];
b0 = translation[c0]; b1 = translation[c1];
source[0] = b0; source[1] = b1;
c0 = source[2]; c1 = source[3];
b0 = translation[c0]; b1 = translation[c1];
source[2] = b0; source[3] = b1;
}
}
void DrawColumnRt1AddPalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
const uint32_t *fg2rgb = _srcblend;
const uint32_t *bg2rgb = _destblend;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4 + hx];
pitch = _pitch * thread->num_cores;
colormap = _colormap;
do {
uint32_t fg = colormap[*source];
uint32_t bg = *dest;
fg = fg2rgb[fg];
bg = bg2rgb[bg];
fg = (fg+bg) | 0x1f07c1f;
*dest = RGB32k.All[fg & (fg>>15)];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt4AddPalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
const uint32_t *fg2rgb = _srcblend;
const uint32_t *bg2rgb = _destblend;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4];
pitch = _pitch * thread->num_cores;
colormap = _colormap;
do {
uint32_t fg = colormap[source[0]];
uint32_t bg = dest[0];
fg = fg2rgb[fg];
bg = bg2rgb[bg];
fg = (fg+bg) | 0x1f07c1f;
dest[0] = RGB32k.All[fg & (fg>>15)];
fg = colormap[source[1]];
bg = dest[1];
fg = fg2rgb[fg];
bg = bg2rgb[bg];
fg = (fg+bg) | 0x1f07c1f;
dest[1] = RGB32k.All[fg & (fg>>15)];
fg = colormap[source[2]];
bg = dest[2];
fg = fg2rgb[fg];
bg = bg2rgb[bg];
fg = (fg+bg) | 0x1f07c1f;
dest[2] = RGB32k.All[fg & (fg>>15)];
fg = colormap[source[3]];
bg = dest[3];
fg = fg2rgb[fg];
bg = bg2rgb[bg];
fg = (fg+bg) | 0x1f07c1f;
dest[3] = RGB32k.All[fg & (fg>>15)];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt1ShadedPalCommand::Execute(DrawerThread *thread)
{
uint32_t *fgstart;
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
fgstart = &Col2RGB8[0][_color];
colormap = _colormap;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4 + hx];
pitch = _pitch * thread->num_cores;
do {
uint32_t val = colormap[*source];
uint32_t fg = fgstart[val<<8];
val = (Col2RGB8[64-val][*dest] + fg) | 0x1f07c1f;
*dest = RGB32k.All[val & (val>>15)];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt4ShadedPalCommand::Execute(DrawerThread *thread)
{
uint32_t *fgstart;
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
fgstart = &Col2RGB8[0][_color];
colormap = _colormap;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4];
pitch = _pitch * thread->num_cores;
do {
uint32_t val;
val = colormap[source[0]];
val = (Col2RGB8[64-val][dest[0]] + fgstart[val<<8]) | 0x1f07c1f;
dest[0] = RGB32k.All[val & (val>>15)];
val = colormap[source[1]];
val = (Col2RGB8[64-val][dest[1]] + fgstart[val<<8]) | 0x1f07c1f;
dest[1] = RGB32k.All[val & (val>>15)];
val = colormap[source[2]];
val = (Col2RGB8[64-val][dest[2]] + fgstart[val<<8]) | 0x1f07c1f;
dest[2] = RGB32k.All[val & (val>>15)];
val = colormap[source[3]];
val = (Col2RGB8[64-val][dest[3]] + fgstart[val<<8]) | 0x1f07c1f;
dest[3] = RGB32k.All[val & (val>>15)];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt1AddClampPalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
const uint32_t *fg2rgb = _srcblend;
const uint32_t *bg2rgb = _destblend;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4 + hx];
pitch = _pitch * thread->num_cores;
colormap = _colormap;
do {
uint32_t a = fg2rgb[colormap[*source]] + bg2rgb[*dest];
uint32_t b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
*dest = RGB32k.All[(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt4AddClampPalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4];
pitch = _pitch * thread->num_cores;
colormap = _colormap;
const uint32_t *fg2rgb = _srcblend;
const uint32_t *bg2rgb = _destblend;
do {
uint32_t a = fg2rgb[colormap[source[0]]] + bg2rgb[dest[0]];
uint32_t b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
dest[0] = RGB32k.All[(a>>15) & a];
a = fg2rgb[colormap[source[1]]] + bg2rgb[dest[1]];
b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
dest[1] = RGB32k.All[(a>>15) & a];
a = fg2rgb[colormap[source[2]]] + bg2rgb[dest[2]];
b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
dest[2] = RGB32k.All[(a>>15) & a];
a = fg2rgb[colormap[source[3]]] + bg2rgb[dest[3]];
b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
dest[3] = RGB32k.All[(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt1SubClampPalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
const uint32_t *fg2rgb = _srcblend;
const uint32_t *bg2rgb = _destblend;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4 + hx];
pitch = _pitch * thread->num_cores;
colormap = _colormap;
do {
uint32_t a = (fg2rgb[colormap[*source]] | 0x40100400) - bg2rgb[*dest];
uint32_t b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k.All[(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt4SubClampPalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
const uint32_t *fg2rgb = _srcblend;
const uint32_t *bg2rgb = _destblend;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4];
pitch = _pitch * thread->num_cores;
colormap = _colormap;
do {
uint32_t a = (fg2rgb[colormap[source[0]]] | 0x40100400) - bg2rgb[dest[0]];
uint32_t b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[0] = RGB32k.All[(a>>15) & a];
a = (fg2rgb[colormap[source[1]]] | 0x40100400) - bg2rgb[dest[1]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[1] = RGB32k.All[(a>>15) & a];
a = (fg2rgb[colormap[source[2]]] | 0x40100400) - bg2rgb[dest[2]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[2] = RGB32k.All[(a>>15) & a];
a = (fg2rgb[colormap[source[3]]] | 0x40100400) - bg2rgb[dest[3]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[3] = RGB32k.All[(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt1RevSubClampPalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
const uint32_t *fg2rgb = _srcblend;
const uint32_t *bg2rgb = _destblend;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4 + hx];
pitch = _pitch * thread->num_cores;
colormap = _colormap;
do {
uint32_t a = (bg2rgb[*dest] | 0x40100400) - fg2rgb[colormap[*source]];
uint32_t b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k.All[(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
void DrawColumnRt4RevSubClampPalCommand::Execute(DrawerThread *thread)
{
const uint8_t *colormap;
uint8_t *source;
uint8_t *dest;
int pitch;
int count = yh - yl + 1;
count = thread->count_for_thread(yl, count);
if (count <= 0)
return;
const uint32_t *fg2rgb = _srcblend;
const uint32_t *bg2rgb = _destblend;
dest = ylookup[yl + thread->skipped_by_thread(yl)] + sx + _destorg;
source = &thread->dc_temp[thread->temp_line_for_thread(yl)*4];
pitch = _pitch * thread->num_cores;
colormap = _colormap;
do {
uint32_t a = (bg2rgb[dest[0]] | 0x40100400) - fg2rgb[colormap[source[0]]];
uint32_t b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[0] = RGB32k.All[(a>>15) & a];
a = (bg2rgb[dest[1]] | 0x40100400) - fg2rgb[colormap[source[1]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[1] = RGB32k.All[(a>>15) & a];
a = (bg2rgb[dest[2]] | 0x40100400) - fg2rgb[colormap[source[2]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[2] = RGB32k.All[(a>>15) & a];
a = (bg2rgb[dest[3]] | 0x40100400) - fg2rgb[colormap[source[3]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[3] = RGB32k.All[(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
}

View file

@ -58,6 +58,38 @@
#include "v_font.h" #include "v_font.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
#include "p_maputl.h" #include "p_maputl.h"
#include "r_thread.h"
CVAR (String, r_viewsize, "", CVAR_NOSET)
CVAR (Bool, r_shadercolormaps, true, CVAR_ARCHIVE)
CUSTOM_CVAR (Int, r_columnmethod, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self != 0 && self != 1)
{
self = 1;
}
else
{ // Trigger the change
setsizeneeded = true;
}
}
CVAR(Int, r_portal_recursions, 4, CVAR_ARCHIVE)
CVAR(Bool, r_highlight_portals, false, CVAR_ARCHIVE)
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
extern cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
extern cycle_t FrameCycles;
extern bool r_showviewer;
cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
namespace swrenderer
{
using namespace drawerargs;
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -88,7 +120,6 @@ extern short *openings;
extern bool r_fakingunderwater; extern bool r_fakingunderwater;
extern "C" int fuzzviewheight; extern "C" int fuzzviewheight;
extern subsector_t *InSubsector; extern subsector_t *InSubsector;
extern bool r_showviewer;
// PRIVATE DATA DECLARATIONS ----------------------------------------------- // PRIVATE DATA DECLARATIONS -----------------------------------------------
@ -100,9 +131,6 @@ bool r_dontmaplines;
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
CVAR (String, r_viewsize, "", CVAR_NOSET)
CVAR (Bool, r_shadercolormaps, true, CVAR_ARCHIVE)
double r_BaseVisibility; double r_BaseVisibility;
double r_WallVisibility; double r_WallVisibility;
double r_FloorVisibility; double r_FloorVisibility;
@ -157,8 +185,6 @@ void (*hcolfunc_post1) (int hx, int sx, int yl, int yh);
void (*hcolfunc_post2) (int hx, int sx, int yl, int yh); void (*hcolfunc_post2) (int hx, int sx, int yl, int yh);
void (*hcolfunc_post4) (int sx, int yl, int yh); void (*hcolfunc_post4) (int sx, int yl, int yh);
cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
static int lastcenteryfrac; static int lastcenteryfrac;
@ -361,26 +387,6 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight,
R_SetVisibility(R_GetVisibility()); R_SetVisibility(R_GetVisibility());
} }
//==========================================================================
//
// CVAR r_columnmethod
//
// Selects which version of the seg renderers to use.
//
//==========================================================================
CUSTOM_CVAR (Int, r_columnmethod, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self != 0 && self != 1)
{
self = 1;
}
else
{ // Trigger the change
setsizeneeded = true;
}
}
//========================================================================== //==========================================================================
// //
// R_Init // R_Init
@ -455,8 +461,6 @@ void R_CopyStackedViewParameters()
// //
//========================================================================== //==========================================================================
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
void R_SetupColormap(player_t *player) void R_SetupColormap(player_t *player)
{ {
realfixedcolormap = NULL; realfixedcolormap = NULL;
@ -574,9 +578,6 @@ void R_SetupFreelook()
// //
//========================================================================== //==========================================================================
CVAR(Int, r_portal_recursions, 4, CVAR_ARCHIVE)
CVAR(Bool, r_highlight_portals, false, CVAR_ARCHIVE)
void R_HighlightPortal (PortalDrawseg* pds) void R_HighlightPortal (PortalDrawseg* pds)
{ {
// [ZZ] NO OVERFLOW CHECKS HERE // [ZZ] NO OVERFLOW CHECKS HERE
@ -853,10 +854,10 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
// [RH] Show off segs if r_drawflat is 1 // [RH] Show off segs if r_drawflat is 1
if (r_drawflat) if (r_drawflat)
{ {
hcolfunc_pre = R_FillColumnHorizP; hcolfunc_pre = R_FillColumnHoriz;
hcolfunc_post1 = rt_copy1col; hcolfunc_post1 = rt_copy1col;
hcolfunc_post4 = rt_copy4cols; hcolfunc_post4 = rt_copy4cols;
colfunc = R_FillColumnP; colfunc = R_FillColumn;
spanfunc = R_FillSpan; spanfunc = R_FillSpan;
} }
else else
@ -950,6 +951,8 @@ void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas,
{ {
const bool savedviewactive = viewactive; const bool savedviewactive = viewactive;
R_BeginDrawerCommands();
viewwidth = width; viewwidth = width;
RenderTarget = canvas; RenderTarget = canvas;
bRenderingToCanvas = true; bRenderingToCanvas = true;
@ -961,6 +964,8 @@ void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas,
R_RenderActorView (actor, dontmaplines); R_RenderActorView (actor, dontmaplines);
R_EndDrawerCommands();
RenderTarget = screen; RenderTarget = screen;
bRenderingToCanvas = false; bRenderingToCanvas = false;
R_ExecuteSetViewSize (); R_ExecuteSetViewSize ();
@ -991,8 +996,6 @@ void R_MultiresInit ()
// Displays statistics about rendering times // Displays statistics about rendering times
// //
//========================================================================== //==========================================================================
extern cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
extern cycle_t FrameCycles;
ADD_STAT (fps) ADD_STAT (fps)
{ {
@ -1072,3 +1075,5 @@ CCMD (clearscancycles)
bestscancycles = HUGE_VAL; bestscancycles = HUGE_VAL;
} }
#endif #endif
}

View file

@ -28,23 +28,26 @@
#include "v_palette.h" #include "v_palette.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
extern double ViewCos;
extern double ViewSin;
extern int viewwindowx;
extern int viewwindowy;
typedef BYTE lighttable_t; // This could be wider for >8 bit display. typedef BYTE lighttable_t; // This could be wider for >8 bit display.
namespace swrenderer
{
// //
// POV related. // POV related.
// //
extern bool bRenderingToCanvas; extern bool bRenderingToCanvas;
extern double ViewCos;
extern double ViewSin;
extern fixed_t viewingrangerecip; extern fixed_t viewingrangerecip;
extern double FocalLengthX, FocalLengthY; extern double FocalLengthX, FocalLengthY;
extern double InvZtoScale; extern double InvZtoScale;
extern double WallTMapScale2; extern double WallTMapScale2;
extern int viewwindowx;
extern int viewwindowy;
extern double CenterX; extern double CenterX;
extern double CenterY; extern double CenterY;
@ -142,5 +145,6 @@ extern DAngle stacked_angle;
extern void R_CopyStackedViewParameters(); extern void R_CopyStackedViewParameters();
}
#endif // __R_MAIN_H__ #endif // __R_MAIN_H__

View file

@ -63,10 +63,14 @@
#pragma warning(disable:4244) #pragma warning(disable:4244)
#endif #endif
CVAR(Bool, tilt, false, 0);
CVAR(Bool, r_skyboxes, true, 0)
EXTERN_CVAR(Int, r_skymode) EXTERN_CVAR(Int, r_skymode)
//EXTERN_CVAR (Int, tx) namespace swrenderer
//EXTERN_CVAR (Int, ty) {
using namespace drawerargs;
extern subsector_t *InSubsector; extern subsector_t *InSubsector;
@ -132,15 +136,12 @@ extern "C" {
// spanend holds the end of a plane span in each screen row // spanend holds the end of a plane span in each screen row
// //
short spanend[MAXHEIGHT]; short spanend[MAXHEIGHT];
BYTE *tiltlighting[MAXWIDTH];
int planeshade; int planeshade;
FVector3 plane_sz, plane_su, plane_sv; FVector3 plane_sz, plane_su, plane_sv;
float planelightfloat; float planelightfloat;
bool plane_shade; bool plane_shade;
fixed_t pviewx, pviewy; fixed_t pviewx, pviewy;
void R_DrawTiltedPlane_ASM (int y, int x1);
} }
float yslope[MAXHEIGHT]; float yslope[MAXHEIGHT];
@ -148,13 +149,6 @@ static fixed_t xscale, yscale;
static double xstepscale, ystepscale; static double xstepscale, ystepscale;
static double basexfrac, baseyfrac; static double basexfrac, baseyfrac;
#ifdef X86_ASM
extern "C" void R_SetSpanSource_ASM (const BYTE *flat);
extern "C" void R_SetSpanSize_ASM (int xbits, int ybits);
extern "C" void R_SetSpanColormap_ASM (BYTE *colormap);
extern "C" void R_SetTiltedSpanSource_ASM (const BYTE *flat);
extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource;
#endif
void R_DrawSinglePlane (visplane_t *, fixed_t alpha, bool additive, bool masked); void R_DrawSinglePlane (visplane_t *, fixed_t alpha, bool additive, bool masked);
//========================================================================== //==========================================================================
@ -249,11 +243,6 @@ void R_MapPlane (int y, int x1)
GlobVis * fabs(CenterY - y), planeshade) << COLORMAPSHIFT); GlobVis * fabs(CenterY - y), planeshade) << COLORMAPSHIFT);
} }
#ifdef X86_ASM
if (ds_colormap != ds_curcolormap)
R_SetSpanColormap_ASM (ds_colormap);
#endif
ds_y = y; ds_y = y;
ds_x1 = x1; ds_x1 = x1;
ds_x2 = x2; ds_x2 = x2;
@ -261,239 +250,15 @@ void R_MapPlane (int y, int x1)
spanfunc (); spanfunc ();
} }
//==========================================================================
//
// R_CalcTiltedLighting
//
// Calculates the lighting for one row of a tilted plane. If the definition
// of GETPALOOKUP changes, this needs to change, too.
//
//==========================================================================
extern "C" {
void R_CalcTiltedLighting (double lval, double lend, int width)
{
double lstep;
BYTE *lightfiller;
BYTE *basecolormapdata = basecolormap->Maps;
int i = 0;
if (width == 0 || lval == lend)
{ // Constant lighting
lightfiller = basecolormapdata + (GETPALOOKUP(lval, planeshade) << COLORMAPSHIFT);
}
else
{
lstep = (lend - lval) / width;
if (lval >= MAXLIGHTVIS)
{ // lval starts "too bright".
lightfiller = basecolormapdata + (GETPALOOKUP(lval, planeshade) << COLORMAPSHIFT);
for (; i <= width && lval >= MAXLIGHTVIS; ++i)
{
tiltlighting[i] = lightfiller;
lval += lstep;
}
}
if (lend >= MAXLIGHTVIS)
{ // lend ends "too bright".
lightfiller = basecolormapdata + (GETPALOOKUP(lend, planeshade) << COLORMAPSHIFT);
for (; width > i && lend >= MAXLIGHTVIS; --width)
{
tiltlighting[width] = lightfiller;
lend -= lstep;
}
}
if (width > 0)
{
lval = FIXED2DBL(planeshade) - lval;
lend = FIXED2DBL(planeshade) - lend;
lstep = (lend - lval) / width;
if (lstep < 0)
{ // Going from dark to light
if (lval < 1.)
{ // All bright
lightfiller = basecolormapdata;
}
else
{
if (lval >= NUMCOLORMAPS)
{ // Starts beyond the dark end
BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
while (lval >= NUMCOLORMAPS && i <= width)
{
tiltlighting[i++] = clight;
lval += lstep;
}
if (i > width)
return;
}
while (i <= width && lval >= 0)
{
tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT);
lval += lstep;
}
lightfiller = basecolormapdata;
}
}
else
{ // Going from light to dark
if (lval >= (NUMCOLORMAPS-1))
{ // All dark
lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
}
else
{
while (lval < 0 && i <= width)
{
tiltlighting[i++] = basecolormapdata;
lval += lstep;
}
if (i > width)
return;
while (i <= width && lval < (NUMCOLORMAPS-1))
{
tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT);
lval += lstep;
}
lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
}
}
}
}
for (; i <= width; i++)
{
tiltlighting[i] = lightfiller;
}
}
} // extern "C"
//========================================================================== //==========================================================================
// //
// R_MapTiltedPlane // R_MapTiltedPlane
// //
//========================================================================== //==========================================================================
void R_MapTiltedPlane(int y, int x1) void R_MapTiltedPlane (int y, int x1)
{ {
int x2 = spanend[y]; R_DrawTiltedSpan(y, x1, spanend[y], plane_sz, plane_su, plane_sv, plane_shade, planeshade, planelightfloat, pviewx, pviewy);
int width = x2 - x1;
double iz, uz, vz;
BYTE *fb;
DWORD u, v;
int i;
iz = plane_sz[2] + plane_sz[1] * (centery - y) + plane_sz[0] * (x1 - centerx);
// Lighting is simple. It's just linear interpolation from start to end
if (plane_shade)
{
uz = (iz + plane_sz[0] * width) * planelightfloat;
vz = iz * planelightfloat;
R_CalcTiltedLighting(vz, uz, width);
}
uz = plane_su[2] + plane_su[1] * (centery - y) + plane_su[0] * (x1 - centerx);
vz = plane_sv[2] + plane_sv[1] * (centery - y) + plane_sv[0] * (x1 - centerx);
fb = ylookup[y] + x1 + dc_destorg;
BYTE vshift = 32 - ds_ybits;
BYTE ushift = vshift - ds_xbits;
int umask = ((1 << ds_xbits) - 1) << ds_ybits;
#if 0 // The "perfect" reference version of this routine. Pretty slow.
// Use it only to see how things are supposed to look.
i = 0;
do
{
double z = 1.f/iz;
u = SQWORD(uz*z) + pviewx;
v = SQWORD(vz*z) + pviewy;
ds_colormap = tiltlighting[i];
fb[i++] = ds_colormap[ds_source[(v >> vshift) | ((u >> ushift) & umask)]];
iz += plane_sz[0];
uz += plane_su[0];
vz += plane_sv[0];
} while (--width >= 0);
#else
//#define SPANSIZE 32
//#define INVSPAN 0.03125f
//#define SPANSIZE 8
//#define INVSPAN 0.125f
#define SPANSIZE 16
#define INVSPAN 0.0625f
double startz = 1.f/iz;
double startu = uz*startz;
double startv = vz*startz;
double izstep, uzstep, vzstep;
izstep = plane_sz[0] * SPANSIZE;
uzstep = plane_su[0] * SPANSIZE;
vzstep = plane_sv[0] * SPANSIZE;
x1 = 0;
width++;
while (width >= SPANSIZE)
{
iz += izstep;
uz += uzstep;
vz += vzstep;
double endz = 1.f/iz;
double endu = uz*endz;
double endv = vz*endz;
DWORD stepu = SQWORD((endu - startu) * INVSPAN);
DWORD stepv = SQWORD((endv - startv) * INVSPAN);
u = SQWORD(startu) + pviewx;
v = SQWORD(startv) + pviewy;
for (i = SPANSIZE-1; i >= 0; i--)
{
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
x1++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = SQWORD(startu);
v = SQWORD(startv);
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
}
else
{
double left = width;
iz += plane_sz[0] * left;
uz += plane_su[0] * left;
vz += plane_sv[0] * left;
double endz = 1.f/iz;
double endu = uz*endz;
double endv = vz*endz;
left = 1.f/left;
DWORD stepu = SQWORD((endu - startu) * left);
DWORD stepv = SQWORD((endv - startv) * left);
u = SQWORD(startu) + pviewx;
v = SQWORD(startv) + pviewy;
for (; width != 0; width--)
{
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
x1++;
u += stepu;
v += stepv;
}
}
}
#endif
} }
//========================================================================== //==========================================================================
@ -502,9 +267,9 @@ void R_MapTiltedPlane(int y, int x1)
// //
//========================================================================== //==========================================================================
void R_MapColoredPlane (int y, int x1) void R_MapColoredPlane(int y, int x1)
{ {
memset (ylookup[y] + x1 + dc_destorg, ds_color, spanend[y] - x1 + 1); R_DrawColoredSpan(y, x1, spanend[y]);
} }
//========================================================================== //==========================================================================
@ -1179,9 +944,6 @@ static void R_DrawSkyStriped (visplane_t *pl)
// //
//========================================================================== //==========================================================================
CVAR (Bool, tilt, false, 0);
//CVAR (Int, pa, 0, 0)
int R_DrawPlanes () int R_DrawPlanes ()
{ {
visplane_t *pl; visplane_t *pl;
@ -1317,7 +1079,6 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
// 9. Put the camera back where it was to begin with. // 9. Put the camera back where it was to begin with.
// //
//========================================================================== //==========================================================================
CVAR (Bool, r_skyboxes, true, 0)
static int numskyboxes; static int numskyboxes;
void R_DrawPortals () void R_DrawPortals ()
@ -1665,13 +1426,6 @@ void R_DrawSkyPlane (visplane_t *pl)
void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked) void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked)
{ {
#ifdef X86_ASM
if (ds_source != ds_cursource)
{
R_SetSpanSource_ASM (ds_source);
}
#endif
if (alpha <= 0) if (alpha <= 0)
{ {
return; return;
@ -1896,14 +1650,6 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t
else else
ds_colormap = basecolormap->Maps, plane_shade = true; ds_colormap = basecolormap->Maps, plane_shade = true;
if (!plane_shade)
{
for (int i = 0; i < viewwidth; ++i)
{
tiltlighting[i] = ds_colormap;
}
}
// Hack in support for 1 x Z and Z x 1 texture sizes // Hack in support for 1 x Z and Z x 1 texture sizes
if (ds_ybits == 0) if (ds_ybits == 0)
{ {
@ -1913,13 +1659,8 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t
{ {
plane_su[2] = plane_su[1] = plane_su[0] = 0; plane_su[2] = plane_su[1] = plane_su[0] = 0;
} }
#if defined(X86_ASM)
if (ds_source != ds_curtiltedsource)
R_SetTiltedSpanSource_ASM (ds_source);
R_MapVisPlane (pl, R_DrawTiltedPlane_ASM);
#else
R_MapVisPlane (pl, R_MapTiltedPlane); R_MapVisPlane (pl, R_MapTiltedPlane);
#endif
} }
//========================================================================== //==========================================================================
@ -2023,3 +1764,5 @@ bool R_PlaneInitData ()
return true; return true;
} }
}

View file

@ -27,6 +27,9 @@
class ASkyViewpoint; class ASkyViewpoint;
namespace swrenderer
{
// //
// The infamous visplane // The infamous visplane
// //
@ -113,4 +116,6 @@ bool R_PlaneInitData (void);
extern visplane_t* floorplane; extern visplane_t* floorplane;
extern visplane_t* ceilingplane; extern visplane_t* ceilingplane;
}
#endif // __R_PLANE_H__ #endif // __R_PLANE_H__

View file

@ -57,10 +57,13 @@
CVAR(Bool, r_np2, true, 0) CVAR(Bool, r_np2, true, 0)
CVAR(Bool, r_fogboundary, true, 0)
CVAR(Bool, r_drawmirrors, true, 0)
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
//CVAR (Int, ty, 8, 0) namespace swrenderer
//CVAR (Int, tx, 8, 0) {
using namespace drawerargs;
#define HEIGHTBITS 12 #define HEIGHTBITS 12
#define HEIGHTSHIFT (FRACBITS-HEIGHTBITS) #define HEIGHTSHIFT (FRACBITS-HEIGHTBITS)
@ -141,16 +144,6 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t
static void wallscan_np2_ds(drawseg_t *ds, int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat); static void wallscan_np2_ds(drawseg_t *ds, int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat);
static void call_wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, bool mask); static void call_wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, bool mask);
//=============================================================================
//
// CVAR r_fogboundary
//
// If true, makes fog look more "real" by shading the walls separating two
// sectors with different fog.
//=============================================================================
CVAR(Bool, r_fogboundary, true, 0)
inline bool IsFogBoundary (sector_t *front, sector_t *back) inline bool IsFogBoundary (sector_t *front, sector_t *back)
{ {
return r_fogboundary && fixedcolormap == NULL && front->ColorMap->Fade && return r_fogboundary && fixedcolormap == NULL && front->ColorMap->Fade &&
@ -158,14 +151,6 @@ inline bool IsFogBoundary (sector_t *front, sector_t *back)
(front->GetTexture(sector_t::ceiling) != skyflatnum || back->GetTexture(sector_t::ceiling) != skyflatnum); (front->GetTexture(sector_t::ceiling) != skyflatnum || back->GetTexture(sector_t::ceiling) != skyflatnum);
} }
//=============================================================================
//
// CVAR r_drawmirrors
//
// Set to false to disable rendering of mirrors
//=============================================================================
CVAR(Bool, r_drawmirrors, true, 0)
// //
// R_RenderMaskedSegRange // R_RenderMaskedSegRange
@ -2994,3 +2979,5 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
done: done:
WallC = savecoord; WallC = savecoord;
} }
}

View file

@ -23,6 +23,9 @@
#ifndef __R_SEGS_H__ #ifndef __R_SEGS_H__
#define __R_SEGS_H__ #define __R_SEGS_H__
namespace swrenderer
{
struct drawseg_t; struct drawseg_t;
void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2); void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2);
@ -70,4 +73,6 @@ extern int CurrentPortalUniq;
extern bool CurrentPortalInSkybox; extern bool CurrentPortalInSkybox;
extern TArray<PortalDrawseg> WallPortals; extern TArray<PortalDrawseg> WallPortals;
}
#endif #endif

View file

@ -80,7 +80,7 @@ extern int numgamesubsectors;
extern AActor* camera; // [RH] camera instead of viewplayer extern AActor* camera; // [RH] camera instead of viewplayer
extern sector_t* viewsector; // [RH] keep track of sector viewing from extern sector_t* viewsector; // [RH] keep track of sector viewing from
extern angle_t xtoviewangle[MAXWIDTH+1]; namespace swrenderer { extern angle_t xtoviewangle[MAXWIDTH+1]; }
extern DAngle FieldOfView; extern DAngle FieldOfView;
int R_FindSkin (const char *name, int pclass); // [RH] Find a skin int R_FindSkin (const char *name, int pclass); // [RH] Find a skin

View file

@ -42,13 +42,20 @@
#include "r_3dfloors.h" #include "r_3dfloors.h"
#include "textures/textures.h" #include "textures/textures.h"
#include "r_data/voxels.h" #include "r_data/voxels.h"
#include "r_thread.h"
namespace swrenderer
{
void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio); void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio);
void R_SetupColormap(player_t *); void R_SetupColormap(player_t *);
void R_SetupFreelook(); void R_SetupFreelook();
void R_InitRenderer(); void R_InitRenderer();
}
using namespace swrenderer;
//========================================================================== //==========================================================================
// //
// DCanvas :: Init // DCanvas :: Init
@ -154,9 +161,11 @@ void FSoftwareRenderer::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &act
void FSoftwareRenderer::RenderView(player_t *player) void FSoftwareRenderer::RenderView(player_t *player)
{ {
R_BeginDrawerCommands();
R_RenderActorView (player->mo); R_RenderActorView (player->mo);
// [RH] Let cameras draw onto textures that were visible this frame. // [RH] Let cameras draw onto textures that were visible this frame.
FCanvasTextureInfo::UpdateAll (); FCanvasTextureInfo::UpdateAll ();
R_EndDrawerCommands();
} }
//========================================================================== //==========================================================================

View file

@ -64,6 +64,21 @@
#include "r_data/voxels.h" #include "r_data/voxels.h"
#include "p_local.h" #include "p_local.h"
#include "p_maputl.h" #include "p_maputl.h"
#include "r_thread.h"
EXTERN_CVAR(Bool, st_scale)
EXTERN_CVAR(Bool, r_shadercolormaps)
EXTERN_CVAR(Int, r_drawfuzz)
EXTERN_CVAR(Bool, r_deathcamera);
EXTERN_CVAR(Bool, r_drawplayersprites)
EXTERN_CVAR(Bool, r_drawvoxels)
CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
//CVAR(Bool, r_splitsprites, true, CVAR_ARCHIVE)
namespace swrenderer
{
using namespace drawerargs;
// [RH] A c-buffer. Used for keeping track of offscreen voxel spans. // [RH] A c-buffer. Used for keeping track of offscreen voxel spans.
@ -95,12 +110,6 @@ extern float MaskedScaleY;
#define BASEXCENTER (160) #define BASEXCENTER (160)
#define BASEYCENTER (100) #define BASEYCENTER (100)
EXTERN_CVAR (Bool, st_scale)
EXTERN_CVAR(Bool, r_shadercolormaps)
EXTERN_CVAR(Int, r_drawfuzz)
EXTERN_CVAR(Bool, r_deathcamera);
CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
// //
// Sprite rotation 0 is facing the viewer, // Sprite rotation 0 is facing the viewer,
// rotation 1 is one angle turn CLOCKWISE around the axis. // rotation 1 is one angle turn CLOCKWISE around the axis.
@ -132,9 +141,6 @@ FTexture *WallSpriteTile;
short zeroarray[MAXWIDTH]; short zeroarray[MAXWIDTH];
short screenheightarray[MAXWIDTH]; short screenheightarray[MAXWIDTH];
EXTERN_CVAR (Bool, r_drawplayersprites)
EXTERN_CVAR (Bool, r_drawvoxels)
// //
// INITIALIZATION FUNCTIONS // INITIALIZATION FUNCTIONS
// //
@ -639,7 +645,7 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop
{ {
return; return;
} }
if (colfunc == fuzzcolfunc || colfunc == R_FillColumnP) if (colfunc == fuzzcolfunc || colfunc == R_FillColumn)
{ {
flags = DVF_OFFSCREEN | DVF_SPANSONLY; flags = DVF_OFFSCREEN | DVF_SPANSONLY;
} }
@ -1758,8 +1764,6 @@ static int sd_comparex (const void *arg1, const void *arg2)
return (*(drawseg_t **)arg2)->x2 - (*(drawseg_t **)arg1)->x2; return (*(drawseg_t **)arg2)->x2 - (*(drawseg_t **)arg1)->x2;
} }
CVAR (Bool, r_splitsprites, true, CVAR_ARCHIVE)
// Split up vissprites that intersect drawsegs // Split up vissprites that intersect drawsegs
void R_SplitVisSprites () void R_SplitVisSprites ()
{ {
@ -2628,7 +2632,7 @@ static void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis)
} }
} }
void R_DrawParticle (vissprite_t *vis) void R_DrawParticle_C (vissprite_t *vis)
{ {
DWORD *bg2rgb; DWORD *bg2rgb;
int spacing; int spacing;
@ -2642,6 +2646,8 @@ void R_DrawParticle (vissprite_t *vis)
R_DrawMaskedSegsBehindParticle (vis); R_DrawMaskedSegsBehindParticle (vis);
DrawerCommandQueue::WaitForWorkers();
// vis->renderflags holds translucency level (0-255) // vis->renderflags holds translucency level (0-255)
{ {
fixed_t fglevel, bglevel; fixed_t fglevel, bglevel;
@ -3237,3 +3243,5 @@ void R_CheckOffscreenBuffer(int width, int height, bool spansonly)
OffscreenBufferWidth = width; OffscreenBufferWidth = width;
OffscreenBufferHeight = height; OffscreenBufferHeight = height;
} }
}

View file

@ -25,6 +25,12 @@
#include "r_bsp.h" #include "r_bsp.h"
struct particle_t;
struct FVoxel;
namespace swrenderer
{
// A vissprite_t is a thing // A vissprite_t is a thing
// that will be drawn during a refresh. // that will be drawn during a refresh.
// I.e. a sprite object that is partly visible. // I.e. a sprite object that is partly visible.
@ -95,9 +101,7 @@ struct vissprite_t
vissprite_t() {} vissprite_t() {}
}; };
struct particle_t; void R_DrawParticle_C (vissprite_t *);
void R_DrawParticle (vissprite_t *);
void R_ProjectParticle (particle_t *, const sector_t *sector, int shade, int fakeside); void R_ProjectParticle (particle_t *, const sector_t *sector, int shade, int fakeside);
extern int MaxVisSprites; extern int MaxVisSprites;
@ -146,5 +150,6 @@ void R_DrawVoxel(const FVector3 &viewpos, FAngle viewangle,
void R_ClipVisSprite (vissprite_t *vis, int xl, int xh); void R_ClipVisSprite (vissprite_t *vis, int xl, int xh);
}
#endif #endif

297
src/r_thread.cpp Normal file
View file

@ -0,0 +1,297 @@
/*
** Renderer multithreading framework
** Copyright (c) 2016 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include <stddef.h>
#include "templates.h"
#include "doomdef.h"
#include "i_system.h"
#include "w_wad.h"
#include "r_local.h"
#include "v_video.h"
#include "doomstat.h"
#include "st_stuff.h"
#include "g_game.h"
#include "g_level.h"
#include "r_thread.h"
CVAR(Bool, r_multithreaded, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
void R_BeginDrawerCommands()
{
DrawerCommandQueue::Begin();
}
void R_EndDrawerCommands()
{
DrawerCommandQueue::End();
}
/////////////////////////////////////////////////////////////////////////////
DrawerCommandQueue *DrawerCommandQueue::Instance()
{
static DrawerCommandQueue queue;
return &queue;
}
DrawerCommandQueue::DrawerCommandQueue()
{
}
DrawerCommandQueue::~DrawerCommandQueue()
{
StopThreads();
}
void* DrawerCommandQueue::AllocMemory(size_t size)
{
// Make sure allocations remain 16-byte aligned
size = (size + 15) / 16 * 16;
auto queue = Instance();
if (queue->memorypool_pos + size > memorypool_size)
return nullptr;
void *data = queue->memorypool + queue->memorypool_pos;
queue->memorypool_pos += size;
return data;
}
void DrawerCommandQueue::Begin()
{
auto queue = Instance();
queue->Finish();
queue->threaded_render++;
}
void DrawerCommandQueue::End()
{
auto queue = Instance();
queue->Finish();
if (queue->threaded_render > 0)
queue->threaded_render--;
}
void DrawerCommandQueue::WaitForWorkers()
{
Instance()->Finish();
}
void DrawerCommandQueue::Finish()
{
auto queue = Instance();
if (queue->commands.empty())
return;
// Give worker threads something to do:
std::unique_lock<std::mutex> start_lock(queue->start_mutex);
queue->active_commands.swap(queue->commands);
queue->run_id++;
start_lock.unlock();
queue->StartThreads();
queue->start_condition.notify_all();
// Do one thread ourselves:
DrawerThread thread;
thread.core = 0;
thread.num_cores = (int)(queue->threads.size() + 1);
struct TryCatchData
{
DrawerCommandQueue *queue;
DrawerThread *thread;
size_t command_index;
} data;
data.queue = queue;
data.thread = &thread;
data.command_index = 0;
VectoredTryCatch(&data,
[](void *data)
{
TryCatchData *d = (TryCatchData*)data;
for (int pass = 0; pass < d->queue->num_passes; pass++)
{
d->thread->pass_start_y = pass * d->queue->rows_in_pass;
d->thread->pass_end_y = (pass + 1) * d->queue->rows_in_pass;
if (pass + 1 == d->queue->num_passes)
d->thread->pass_end_y = MAX(d->thread->pass_end_y, MAXHEIGHT);
size_t size = d->queue->active_commands.size();
for (d->command_index = 0; d->command_index < size; d->command_index++)
{
auto &command = d->queue->active_commands[d->command_index];
command->Execute(d->thread);
}
}
},
[](void *data, const char *reason, bool fatal)
{
TryCatchData *d = (TryCatchData*)data;
ReportDrawerError(d->queue->active_commands[d->command_index], true, reason, fatal);
});
// Wait for everyone to finish:
std::unique_lock<std::mutex> end_lock(queue->end_mutex);
queue->end_condition.wait(end_lock, [&]() { return queue->finished_threads == queue->threads.size(); });
if (!queue->thread_error.IsEmpty())
{
static bool first = true;
if (queue->thread_error_fatal)
I_FatalError("%s", queue->thread_error.GetChars());
else if (first)
Printf("%s\n", queue->thread_error.GetChars());
first = false;
}
// Clean up batch:
for (auto &command : queue->active_commands)
command->~DrawerCommand();
queue->active_commands.clear();
queue->memorypool_pos = 0;
queue->finished_threads = 0;
}
void DrawerCommandQueue::StartThreads()
{
if (!threads.empty())
return;
int num_threads = std::thread::hardware_concurrency();
if (num_threads == 0)
num_threads = 4;
threads.resize(num_threads - 1);
for (int i = 0; i < num_threads - 1; i++)
{
DrawerCommandQueue *queue = this;
DrawerThread *thread = &threads[i];
thread->core = i + 1;
thread->num_cores = num_threads;
thread->thread = std::thread([=]()
{
int run_id = 0;
while (true)
{
// Wait until we are signalled to run:
std::unique_lock<std::mutex> start_lock(queue->start_mutex);
queue->start_condition.wait(start_lock, [&]() { return queue->run_id != run_id || queue->shutdown_flag; });
if (queue->shutdown_flag)
break;
run_id = queue->run_id;
start_lock.unlock();
// Do the work:
struct TryCatchData
{
DrawerCommandQueue *queue;
DrawerThread *thread;
size_t command_index;
} data;
data.queue = queue;
data.thread = thread;
data.command_index = 0;
VectoredTryCatch(&data,
[](void *data)
{
TryCatchData *d = (TryCatchData*)data;
for (int pass = 0; pass < d->queue->num_passes; pass++)
{
d->thread->pass_start_y = pass * d->queue->rows_in_pass;
d->thread->pass_end_y = (pass + 1) * d->queue->rows_in_pass;
if (pass + 1 == d->queue->num_passes)
d->thread->pass_end_y = MAX(d->thread->pass_end_y, MAXHEIGHT);
size_t size = d->queue->active_commands.size();
for (d->command_index = 0; d->command_index < size; d->command_index++)
{
auto &command = d->queue->active_commands[d->command_index];
command->Execute(d->thread);
}
}
},
[](void *data, const char *reason, bool fatal)
{
TryCatchData *d = (TryCatchData*)data;
ReportDrawerError(d->queue->active_commands[d->command_index], true, reason, fatal);
});
// Notify main thread that we finished:
std::unique_lock<std::mutex> end_lock(queue->end_mutex);
queue->finished_threads++;
end_lock.unlock();
queue->end_condition.notify_all();
}
});
}
}
void DrawerCommandQueue::StopThreads()
{
std::unique_lock<std::mutex> lock(start_mutex);
shutdown_flag = true;
lock.unlock();
start_condition.notify_all();
for (auto &thread : threads)
thread.thread.join();
threads.clear();
lock.lock();
shutdown_flag = false;
}
void DrawerCommandQueue::ReportDrawerError(DrawerCommand *command, bool worker_thread, const char *reason, bool fatal)
{
if (worker_thread)
{
std::unique_lock<std::mutex> end_lock(Instance()->end_mutex);
if (Instance()->thread_error.IsEmpty() || (!Instance()->thread_error_fatal && fatal))
{
Instance()->thread_error = reason + (FString)": " + command->DebugInfo();
Instance()->thread_error_fatal = fatal;
}
}
else
{
static bool first = true;
if (fatal)
I_FatalError("%s: %s", reason, command->DebugInfo().GetChars());
else if (first)
Printf("%s: %s\n", reason, command->DebugInfo().GetChars());
first = false;
}
}
void VectoredTryCatch(void *data, void(*tryBlock)(void *data), void(*catchBlock)(void *data, const char *reason, bool fatal))
{
tryBlock(data);
}

235
src/r_thread.h Normal file
View file

@ -0,0 +1,235 @@
/*
** Renderer multithreading framework
** Copyright (c) 2016 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#pragma once
#include "r_draw.h"
#include <vector>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
// Use multiple threads when drawing
EXTERN_CVAR(Bool, r_multithreaded)
// Redirect drawer commands to worker threads
void R_BeginDrawerCommands();
// Wait until all drawers finished executing
void R_EndDrawerCommands();
// Worker data for each thread executing drawer commands
class DrawerThread
{
public:
std::thread thread;
// Thread line index of this thread
int core = 0;
// Number of active threads
int num_cores = 1;
// Range of rows processed this pass
int pass_start_y = 0;
int pass_end_y = MAXHEIGHT;
// Working buffer used by Rt drawers
uint8_t dc_temp_buff[MAXHEIGHT * 4];
uint8_t *dc_temp = nullptr;
// Working buffer used by Rt drawers, true color edition
uint32_t dc_temp_rgbabuff_rgba[MAXHEIGHT * 4];
uint32_t *dc_temp_rgba = nullptr;
// Working buffer used by the tilted (sloped) span drawer
const uint8_t *tiltlighting[MAXWIDTH];
// Checks if a line is rendered by this thread
bool line_skipped_by_thread(int line)
{
return line < pass_start_y || line >= pass_end_y || line % num_cores != core;
}
// The number of lines to skip to reach the first line to be rendered by this thread
int skipped_by_thread(int first_line)
{
int pass_skip = MAX(pass_start_y - first_line, 0);
int core_skip = (num_cores - (first_line + pass_skip - core) % num_cores) % num_cores;
return pass_skip + core_skip;
}
// The number of lines to be rendered by this thread
int count_for_thread(int first_line, int count)
{
int lines_until_pass_end = MAX(pass_end_y - first_line, 0);
count = MIN(count, lines_until_pass_end);
int c = (count - skipped_by_thread(first_line) + num_cores - 1) / num_cores;
return MAX(c, 0);
}
// Calculate the dest address for the first line to be rendered by this thread
template<typename T>
T *dest_for_thread(int first_line, int pitch, T *dest)
{
return dest + skipped_by_thread(first_line) * pitch;
}
// The first line in the dc_temp buffer used this thread
int temp_line_for_thread(int first_line)
{
return (first_line + skipped_by_thread(first_line)) / num_cores;
}
};
// Task to be executed by each worker thread
class DrawerCommand
{
protected:
int _dest_y;
void DetectRangeError(uint32_t *&dest, int &dest_y, int &count)
{
#if defined(_MSC_VER) && defined(_DEBUG)
if (dest_y < 0 || count < 0 || dest_y + count > swrenderer::drawerargs::dc_destheight)
__debugbreak(); // Buffer overrun detected!
#endif
if (dest_y < 0)
{
count += dest_y;
dest_y = 0;
dest = (uint32_t*)swrenderer::drawerargs::dc_destorg;
}
else if (dest_y >= swrenderer::drawerargs::dc_destheight)
{
dest_y = 0;
count = 0;
}
if (count < 0 || count > MAXHEIGHT) count = 0;
if (dest_y + count >= swrenderer::drawerargs::dc_destheight)
count = swrenderer::drawerargs::dc_destheight - dest_y;
}
public:
DrawerCommand()
{
_dest_y = static_cast<int>((swrenderer::drawerargs::dc_dest - swrenderer::drawerargs::dc_destorg) / (swrenderer::drawerargs::dc_pitch));
}
virtual ~DrawerCommand() { }
virtual void Execute(DrawerThread *thread) = 0;
virtual FString DebugInfo() = 0;
};
void VectoredTryCatch(void *data, void(*tryBlock)(void *data), void(*catchBlock)(void *data, const char *reason, bool fatal));
// Manages queueing up commands and executing them on worker threads
class DrawerCommandQueue
{
enum { memorypool_size = 16 * 1024 * 1024 };
char memorypool[memorypool_size];
size_t memorypool_pos = 0;
std::vector<DrawerCommand *> commands;
std::vector<DrawerThread> threads;
std::mutex start_mutex;
std::condition_variable start_condition;
std::vector<DrawerCommand *> active_commands;
bool shutdown_flag = false;
int run_id = 0;
std::mutex end_mutex;
std::condition_variable end_condition;
size_t finished_threads = 0;
FString thread_error;
bool thread_error_fatal = false;
int threaded_render = 0;
DrawerThread single_core_thread;
int num_passes = 1;
int rows_in_pass = MAXHEIGHT;
void StartThreads();
void StopThreads();
void Finish();
static DrawerCommandQueue *Instance();
static void ReportDrawerError(DrawerCommand *command, bool worker_thread, const char *reason, bool fatal);
DrawerCommandQueue();
~DrawerCommandQueue();
public:
// Allocate memory valid for the duration of a command execution
static void* AllocMemory(size_t size);
// Queue command to be executed by drawer worker threads
template<typename T, typename... Types>
static void QueueCommand(Types &&... args)
{
auto queue = Instance();
if (queue->threaded_render == 0 || !r_multithreaded)
{
T command(std::forward<Types>(args)...);
VectoredTryCatch(&command,
[](void *data)
{
T *c = (T*)data;
c->Execute(&Instance()->single_core_thread);
},
[](void *data, const char *reason, bool fatal)
{
T *c = (T*)data;
ReportDrawerError(c, false, reason, fatal);
});
}
else
{
void *ptr = AllocMemory(sizeof(T));
if (!ptr) // Out of memory - render what we got
{
queue->Finish();
ptr = AllocMemory(sizeof(T));
if (!ptr)
return;
}
T *command = new (ptr)T(std::forward<Types>(args)...);
queue->commands.push_back(command);
}
}
// Redirects all drawing commands to worker threads until End is called
// Begin/End blocks can be nested.
static void Begin();
// End redirection and wait until all worker threads finished executing
static void End();
// Waits until all worker threads finished executing
static void WaitForWorkers();
};

View file

@ -132,6 +132,9 @@ void DCanvas::DrawTexture (FTexture *img, double x, double y, int tags_first, ..
void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
{ {
#ifndef NO_SWRENDER #ifndef NO_SWRENDER
using namespace swrenderer;
using namespace drawerargs;
FTexture::Span unmaskedSpan[2]; FTexture::Span unmaskedSpan[2];
const FTexture::Span **spanptr, *spans; const FTexture::Span **spanptr, *spans;
static short bottomclipper[MAXWIDTH], topclipper[MAXWIDTH]; static short bottomclipper[MAXWIDTH], topclipper[MAXWIDTH];
@ -1285,6 +1288,9 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
FDynamicColormap *colormap, int lightlevel, int bottomclip) FDynamicColormap *colormap, int lightlevel, int bottomclip)
{ {
#ifndef NO_SWRENDER #ifndef NO_SWRENDER
using namespace swrenderer;
using namespace drawerargs;
// Use an equation similar to player sprites to determine shade // Use an equation similar to player sprites to determine shade
fixed_t shade = LIGHT2SHADE(lightlevel) - 12*FRACUNIT; fixed_t shade = LIGHT2SHADE(lightlevel) - 12*FRACUNIT;
float topy, boty, leftx, rightx; float topy, boty, leftx, rightx;
@ -1352,7 +1358,7 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
// Setup constant texture mapping parameters. // Setup constant texture mapping parameters.
R_SetupSpanBits(tex); R_SetupSpanBits(tex);
R_SetSpanColormap(colormap != NULL ? &colormap->Maps[clamp(shade >> FRACBITS, 0, NUMCOLORMAPS-1) * 256] : identitymap); R_SetSpanColormap(colormap != NULL ? &colormap->Maps[clamp(shade >> FRACBITS, 0, NUMCOLORMAPS-1) * 256] : identitymap);
R_SetSpanSource(tex->GetPixels()); R_SetSpanSource(tex);
if (ds_xbits != 0) if (ds_xbits != 0)
{ {
scalex = double(1u << (32 - ds_xbits)) / scalex; scalex = double(1u << (32 - ds_xbits)) / scalex;

View file

@ -1375,17 +1375,16 @@ void D3DFB::Draw3DPart(bool copy3d)
D3DCOLOR color0, color1; D3DCOLOR color0, color1;
if (Accel2D) if (Accel2D)
{ {
if (realfixedcolormap == NULL) auto &map = swrenderer::realfixedcolormap;
if (map == NULL)
{ {
color0 = 0; color0 = 0;
color1 = 0xFFFFFFF; color1 = 0xFFFFFFF;
} }
else else
{ {
color0 = D3DCOLOR_COLORVALUE(realfixedcolormap->ColorizeStart[0]/2, color0 = D3DCOLOR_COLORVALUE(map->ColorizeStart[0] / 2, map->ColorizeStart[1] / 2, map->ColorizeStart[2] / 2, 0);
realfixedcolormap->ColorizeStart[1]/2, realfixedcolormap->ColorizeStart[2]/2, 0); color1 = D3DCOLOR_COLORVALUE(map->ColorizeEnd[0] / 2, map->ColorizeEnd[1] / 2, map->ColorizeEnd[2] / 2, 1);
color1 = D3DCOLOR_COLORVALUE(realfixedcolormap->ColorizeEnd[0]/2,
realfixedcolormap->ColorizeEnd[1]/2, realfixedcolormap->ColorizeEnd[2]/2, 1);
SetPixelShader(Shaders[SHADER_SpecialColormapPal]); SetPixelShader(Shaders[SHADER_SpecialColormapPal]);
} }
} }