Merge remote-tracking branch 'origin/master' into polybackend

This commit is contained in:
Magnus Norddahl 2019-06-10 22:46:32 +02:00
commit bb47230f79
126 changed files with 2186 additions and 1293 deletions

View file

@ -6,37 +6,23 @@ branches:
clone_depth: 10
image:
- Visual Studio 2019
- Visual Studio 2015
environment:
matrix:
- GENERATOR: "Visual Studio 14 2015"
CONFIGURATION: Release
TOOLSET: v140_xp
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
- GENERATOR: "Visual Studio 14 2015 Win64"
CONFIGURATION: Release
TOOLSET: v140
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
- GENERATOR: "Visual Studio 15 2017"
CONFIGURATION: Release
TOOLSET: v141_xp
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
- GENERATOR: "Visual Studio 15 2017 Win64"
CONFIGURATION: Release
TOOLSET: v141
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
- GENERATOR: "Visual Studio 15 2017 Win64"
CONFIGURATION: Debug
TOOLSET: v141
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
- ARCH: x64
- ARCH: Win32
build_script:
- md build
- cd build
- cmake -G "%GENERATOR%" -T "%TOOLSET%" -DPK3_QUIET_ZIPDIR=YES ..
- cmake --build . --config "%CONFIGURATION%" -- -maxcpucount -verbosity:minimal
- cmake -A %ARCH% -DPK3_QUIET_ZIPDIR=YES ..
- cmake --build . --config Release -- -maxcpucount -verbosity:minimal
after_build:
- set OUTPUT_DIR=%APPVEYOR_BUILD_FOLDER%\build\%CONFIGURATION%\
- set OUTPUT_DIR=%APPVEYOR_BUILD_FOLDER%\build\Release\
- 7z a ..\gzdoom.zip "%OUTPUT_DIR%gzdoom.exe" "%OUTPUT_DIR%*.pk3"
artifacts:

1
.gitignore vendored
View file

@ -24,3 +24,4 @@
/build_vc2017-32
/build2
/build_vc2019-64
/build_vc2019-32

View file

@ -239,7 +239,21 @@ else()
else()
set( ALL_C_FLAGS "-ffp-contract=off" )
endif()
if ( UNIX )
include(CheckSymbolExists)
check_symbol_exists( "fts_set" "fts.h" HAVE_FTS )
if ( NOT HAVE_FTS )
include ( FindPkgConfig )
pkg_check_modules( MUSL_FTS musl-fts )
if ( MUSL_FTS_FOUND )
set ( ALL_C_FLAGS "${ALL_C_FLAGS} ${MUSL_FTS_LDFLAGS}" )
else ( MUSL_FTS_FOUND )
message (ERROR "fts_* functions not found in the system" )
endif ( MUSL_FTS_FOUND )
endif ( NOT HAVE_FTS )
endif ( UNIX )
set( REL_C_FLAGS "" )
set( DEB_C_FLAGS "" )
@ -310,6 +324,19 @@ else()
set( ZLIB_LIBRARY z )
endif()
if( HAVE_VM_JIT AND UNIX )
check_symbol_exists( "backtrace" "execinfo.h" HAVE_BACKTRACE )
if( NOT HAVE_BACKTRACE )
set( CMAKE_REQUIRED_FLAGS "-lexecinfo" )
check_symbol_exists( "backtrace" "execinfo.h" HAVE_LIBEXECINFO )
if( HAVE_LIBEXECINFO )
set( ALL_C_FLAGS "${ALL_C_FLAGS} -lexecinfo" )
else( HAVE_LIBEXECINFO )
set( HAVE_VM_JIT NO )
endif( HAVE_LIBEXECINFO )
endif( NOT HAVE_BACKTRACE )
endif( HAVE_VM_JIT AND UNIX )
if( ${HAVE_VM_JIT} )
if( ASMJIT_FOUND AND NOT FORCE_INTERNAL_ASMJIT )
message( STATUS "Using system asmjit, includes found at ${ASMJIT_INCLUDE_DIR}" )

View file

@ -1,10 +0,0 @@
Some software in this archive may be from the book _Methods and
Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
International, 1989) or from the Cephes Mathematical Library, a
commercial product. In either event, it is copyrighted by the author.
What you see here may be used freely but it comes with no support or
guarantee.
Stephen L. Moshier
moshier@na-net.ornl.gov

View file

@ -1291,6 +1291,7 @@ set (PCH_SOURCES
utility/nodebuilder/nodebuild_utility.cpp
utility/sc_man.cpp
utility/stats.cpp
utility/atterm.cpp
utility/cmdlib.cpp
utility/colormatcher.cpp
utility/configfile.cpp
@ -1451,10 +1452,9 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
# Need to enable intrinsics for these files.
if( SSE_MATTERS )
set_source_files_properties(
gl/system/gl_swframebuffer.cpp
polyrenderer/poly_all.cpp
swrenderer/r_all.cpp
x86.cpp
rendering/polyrenderer/poly_all.cpp
rendering/swrenderer/r_all.cpp
utility/x86.cpp
PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
endif()
endif()

View file

@ -74,7 +74,7 @@ extern bool insave;
CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH)
CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO)
CVAR (Bool, cl_blockcheats, false, 0)
CVAR (Int, cl_blockcheats, 0, 0)
CCMD (toggleconsole)
{
@ -88,9 +88,9 @@ bool CheckCheatmode (bool printmsg)
if (printmsg) Printf ("sv_cheats must be true to enable this command.\n");
return true;
}
else if (cl_blockcheats)
else if (cl_blockcheats != 0)
{
if (printmsg) Printf ("cl_blockcheats is turned on and disabled this command.\n");
if (printmsg && cl_blockcheats == 1) Printf ("cl_blockcheats is turned on and disabled this command.\n");
return true;
}
else

View file

@ -123,6 +123,8 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
{
if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared)
{
if (mBufferWasCleared)
mLastLineNeedsUpdate = false;
m_BrokenConsoleText.Clear();
mBrokenStart.Clear();
mBrokenStart.Push(0);

View file

@ -102,6 +102,7 @@
#include "i_system.h"
#include "g_cvars.h"
#include "r_data/r_vanillatrans.h"
#include "atterm.h"
EXTERN_CVAR(Bool, hud_althud)
EXTERN_CVAR(Int, vr_mode)

View file

@ -50,6 +50,7 @@
#include "types.h"
#include "scriptutil.h"
#include "i_system.h"
#include "atterm.h"
// MACROS ------------------------------------------------------------------

View file

@ -302,6 +302,11 @@ inline float DEG2RAD(float deg)
return deg * float(M_PI / 180.0);
}
inline double DEG2RAD(double deg)
{
return deg * (M_PI / 180.0);
}
inline float RAD2DEG(float deg)
{
return deg * float(180. / M_PI);

View file

@ -49,6 +49,7 @@
#include "vm.h"
#include "i_system.h"
#include "utf8.h"
#include "atterm.h"
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
enum

View file

@ -802,7 +802,9 @@ void DBaseStatusBar::CallTick()
void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer)
{
DHUDMessageBase *old = NULL;
TObjPtr<DHUDMessageBase *>*prev;
DObject* pointing;
TObjPtr<DHUDMessageBase *>*prevp;
DHUDMessageBase* prev;
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
if (old != NULL)
@ -816,20 +818,25 @@ void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer
layer = HUDMSGLayer_Default;
}
prev = &Messages[layer];
pointing = this;
prevp = &Messages[layer];
prev = *prevp;
// The ID serves as a priority, where lower numbers appear in front of
// higher numbers. (i.e. The list is sorted in descending order, since
// it gets drawn back to front.)
while (*prev != NULL && (*prev)->SBarID > id)
while (prev != NULL && prev->SBarID > id)
{
prev = &(*prev)->Next;
pointing = prev;
prevp = &prev->Next;
prev = *prevp;
}
msg->Next = *prev;
msg->Next = prev;
msg->SBarID = id;
*prev = msg;
GC::WriteBarrier(msg);
*prevp = msg;
GC::WriteBarrier(msg, prev);
GC::WriteBarrier(pointing, msg);
}
//---------------------------------------------------------------------------
@ -843,15 +850,18 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (DHUDMessageBase *msg)
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessageBase *probe = Messages[i];
DObject* pointing = this;
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
while (probe && probe != msg)
{
pointing = probe;
prev = &probe->Next;
probe = probe->Next;
}
if (probe != NULL)
{
GC::WriteBarrier(pointing, probe->Next);
*prev = probe->Next;
probe->Next = nullptr;
return probe;
@ -864,16 +874,19 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (uint32_t id)
{
for (size_t i = 0; i < countof(Messages); ++i)
{
DObject* pointing = this;
DHUDMessageBase *probe = Messages[i];
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
while (probe && probe->SBarID != id)
{
pointing = probe;
prev = &probe->Next;
probe = probe->Next;
}
if (probe != NULL)
{
GC::WriteBarrier(pointing, probe->Next);
*prev = probe->Next;
probe->Next = nullptr;
return probe;

View file

@ -50,6 +50,7 @@
#include "g_levellocals.h"
#include "events.h"
#include "i_system.h"
#include "atterm.h"
static TArray<cluster_info_t> wadclusterinfos;
TArray<level_info_t> wadlevelinfos;

View file

@ -49,7 +49,7 @@ static void SetDoom2Wad()
{
if (Doom2Wad == -1)
{
FString iwad = Wads.GetWadFullName(1);
FString iwad = Wads.GetWadFullName(Wads.GetIwadNum());
iwad.ToLower();
if (iwad.IndexOf("plutonia") >= 0) Doom2Wad = 1;
else if (iwad.IndexOf("tnt") >= 0) Doom2Wad = 2;

View file

@ -62,6 +62,7 @@
#include "st_start.h"
#include "m_misc.h"
#include "doomerrors.h"
#include "atterm.h"
#include "i_net.h"

View file

@ -66,6 +66,7 @@
#include "gameconfigfile.h"
#include "gstrings.h"
#include "atterm.h"
FGameConfigFile *GameConfig;

View file

@ -767,6 +767,11 @@ bool MapLoader::LoadExtendedNodes (FileReader &dalump, uint32_t id)
static bool P_CheckV4Nodes(MapData *map)
{
if (map->Size(ML_NODES) == 0)
{
return false;
}
char header[8];
map->Read(ML_NODES, header, 8);

View file

@ -510,8 +510,6 @@ void MapLoader::ParseReplies (const char *name, int pos, FStrifeDialogueReply **
{
FStringf label("$TXT_RPLY%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Reply).GetChars());
reply->Reply = GStrings.exists(label.GetChars() + 1)? label : FString(rsp->Reply);
reply->Reply = label;
}
else
{

View file

@ -50,6 +50,7 @@
#include "gstrings.h"
#include "teaminfo.h"
#include "r_data/sprites.h"
#include "atterm.h"
void ClearSaveGames();
@ -135,6 +136,7 @@ DEFINE_ACTION_FUNCTION(FOptionValues, GetText)
void DeinitMenus()
{
M_ClearMenus();
{
FOptionMap::Iterator it(OptionValues);
@ -148,7 +150,6 @@ void DeinitMenus()
}
MenuDescriptors.Clear();
OptionValues.Clear();
CurrentMenu = nullptr;
savegameManager.ClearSaveGames();
}

View file

@ -4819,7 +4819,10 @@ void AActor::OnDestroy ()
// note that this differs from ThingSpawned in that you can actually override OnDestroy to avoid calling the hook.
// but you can't really do that without utterly breaking the game, so it's ok.
// note: if OnDestroy is ever made optional, E_WorldThingDestroyed should still be called for ANY thing.
Level->localEventManager->WorldThingDestroyed(this);
if (Level != nullptr)
{
Level->localEventManager->WorldThingDestroyed(this);
}
DeleteAttachedLights();
ClearRenderSectorList();

View file

@ -75,6 +75,7 @@
#include "i_system.h"
#include "v_video.h"
#include "fragglescript/t_script.h"
#include "atterm.h"
extern AActor *SpawnMapThing (int index, FMapThing *mthing, int position);

View file

@ -42,6 +42,7 @@
#include "m_joy.h"
#include "templates.h"
#include "v_text.h"
#include "atterm.h"
EXTERN_CVAR(Bool, joy_axespolling)

View file

@ -33,6 +33,7 @@
#include "i_common.h"
#include "s_sound.h"
#include "atterm.h"
#include <sys/sysctl.h>
@ -61,60 +62,6 @@ EXTERN_CVAR(Bool, vid_vsync )
// ---------------------------------------------------------------------------
namespace
{
// The maximum number of functions that can be registered with atterm.
const size_t MAX_TERMS = 64;
void (*TermFuncs[MAX_TERMS])();
const char *TermNames[MAX_TERMS];
size_t NumTerms;
} // unnamed namespace
// Expose this for i_main_except.cpp
void call_terms()
{
while (NumTerms > 0)
{
TermFuncs[--NumTerms]();
}
}
void addterm(void (*func)(), const char *name)
{
// Make sure this function wasn't already registered.
for (size_t i = 0; i < NumTerms; ++i)
{
if (TermFuncs[i] == func)
{
return;
}
}
if (NumTerms == MAX_TERMS)
{
func();
I_FatalError("Too many exit functions registered.");
}
TermNames[NumTerms] = name;
TermFuncs[NumTerms] = func;
++NumTerms;
}
void popterm()
{
if (NumTerms)
{
--NumTerms;
}
}
void Mac_I_FatalError(const char* const message)
{

View file

@ -36,9 +36,9 @@
#include "doomerrors.h"
#include "vm.h"
#include "atterm.h"
// Import some functions from i_main.mm
void call_terms();
void Mac_I_FatalError(const char* const message);
void OriginalMainTry(int argc, char** argv);

View file

@ -48,6 +48,7 @@
#include "v_text.h"
#include "x86.h"
#include "cmdlib.h"
#include "atterm.h"
EXTERN_CVAR(String, language)

View file

@ -54,6 +54,7 @@
#include "v_text.h"
#include "version.h"
#include "doomerrors.h"
#include "atterm.h"
#include "gl/system/gl_framebuffer.h"
#include "vulkan/system/vk_framebuffer.h"

View file

@ -89,10 +89,6 @@ void I_Quit (void);
void I_Tactile (int on, int off, int total);
void addterm (void (*func)(void), const char *name);
#define atterm(t) addterm (t, #t)
void popterm ();
void I_DebugPrint (const char *cp);
// Print a console string

View file

@ -43,6 +43,7 @@
#include "m_argv.h"
#include "doomerrors.h"
#include "swrenderer/r_swrenderer.h"
#include "atterm.h"
IVideo *Video;

View file

@ -306,54 +306,63 @@ void MessagePump (const SDL_Event &sev)
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEMOTION:
if (!GUICapture || sev.button.button == 4 || sev.button.button == 5)
if (!GUICapture)
{
if(sev.type != SDL_MOUSEMOTION)
event.type = sev.type == SDL_MOUSEBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
switch (sev.button.button)
{
event.type = sev.type == SDL_MOUSEBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
/* These button mappings work with my Gentoo system using the
* evdev driver and a Logitech MX510 mouse. Whether or not they
* carry over to other Linux systems, I have no idea, but I sure
* hope so. (Though buttons 11 and 12 are kind of useless, since
* they also trigger buttons 4 and 5.)
*/
switch (sev.button.button)
{
case SDL_BUTTON_LEFT: event.data1 = KEY_MOUSE1; break;
case SDL_BUTTON_MIDDLE: event.data1 = KEY_MOUSE3; break;
case SDL_BUTTON_RIGHT: event.data1 = KEY_MOUSE2; break;
case 8: event.data1 = KEY_MOUSE4; break; // For whatever reason my side mouse buttons are here.
case 9: event.data1 = KEY_MOUSE5; break;
case SDL_BUTTON_X1: event.data1 = KEY_MOUSE6; break; // And these don't exist
case SDL_BUTTON_X2: event.data1 = KEY_MOUSE7; break;
case 6: event.data1 = KEY_MOUSE8; break;
default: printf("SDL mouse button %s %d\n",
sev.type == SDL_MOUSEBUTTONDOWN ? "down" : "up", sev.button.button); break;
}
if (event.data1 != 0)
{
D_PostEvent(&event);
}
case SDL_BUTTON_LEFT: event.data1 = KEY_MOUSE1; break;
case SDL_BUTTON_MIDDLE: event.data1 = KEY_MOUSE3; break;
case SDL_BUTTON_RIGHT: event.data1 = KEY_MOUSE2; break;
case SDL_BUTTON_X1: event.data1 = KEY_MOUSE4; break;
case SDL_BUTTON_X2: event.data1 = KEY_MOUSE5; break;
case 6: event.data1 = KEY_MOUSE6; break;
case 7: event.data1 = KEY_MOUSE7; break;
case 8: event.data1 = KEY_MOUSE8; break;
default: printf("SDL mouse button %s %d\n",
sev.type == SDL_MOUSEBUTTONDOWN ? "down" : "up", sev.button.button); break;
}
if (event.data1 != 0)
{
D_PostEvent(&event);
}
}
else if (sev.type == SDL_MOUSEMOTION || (sev.button.button >= 1 && sev.button.button <= 3))
else if ((sev.button.button >= SDL_BUTTON_LEFT && sev.button.button <= SDL_BUTTON_X2))
{
int x, y;
SDL_GetMouseState (&x, &y);
SDL_GetMouseState(&x, &y);
event.type = EV_GUI_Event;
event.data1 = x;
event.data2 = y;
screen->ScaleCoordsFromWindow(event.data1, event.data2);
event.type = EV_GUI_Event;
if(sev.type == SDL_MOUSEMOTION)
event.subtype = EV_GUI_MouseMove;
if (sev.type == SDL_MOUSEBUTTONDOWN)
{
switch(sev.button.button)
{
case SDL_BUTTON_LEFT: event.subtype = EV_GUI_LButtonDown; break;
case SDL_BUTTON_MIDDLE: event.subtype = EV_GUI_MButtonDown; break;
case SDL_BUTTON_RIGHT: event.subtype = EV_GUI_RButtonDown; break;
case SDL_BUTTON_X1: event.subtype = EV_GUI_BackButtonDown; break;
case SDL_BUTTON_X2: event.subtype = EV_GUI_FwdButtonDown; break;
default: assert(false); event.subtype = EV_GUI_None; break;
}
}
else
{
event.subtype = sev.type == SDL_MOUSEBUTTONDOWN ? EV_GUI_LButtonDown : EV_GUI_LButtonUp;
event.subtype += (sev.button.button - 1) * 3;
switch(sev.button.button)
{
case SDL_BUTTON_LEFT: event.subtype = EV_GUI_LButtonUp; break;
case SDL_BUTTON_MIDDLE: event.subtype = EV_GUI_MButtonUp; break;
case SDL_BUTTON_RIGHT: event.subtype = EV_GUI_RButtonUp; break;
case SDL_BUTTON_X1: event.subtype = EV_GUI_BackButtonUp; break;
case SDL_BUTTON_X2: event.subtype = EV_GUI_FwdButtonUp; break;
default: assert(false); event.subtype = EV_GUI_None; break;
}
}
SDL_Keymod kmod = SDL_GetModState();
@ -365,15 +374,41 @@ void MessagePump (const SDL_Event &sev)
}
break;
case SDL_MOUSEMOTION:
if (GUICapture)
{
event.data1 = sev.motion.x;
event.data2 = sev.motion.y;
screen->ScaleCoordsFromWindow(event.data1, event.data2);
event.type = EV_GUI_Event;
event.subtype = EV_GUI_MouseMove;
SDL_Keymod kmod = SDL_GetModState();
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
((kmod & KMOD_ALT) ? GKM_ALT : 0);
D_PostEvent(&event);
}
break;
case SDL_MOUSEWHEEL:
if (GUICapture)
{
event.type = EV_GUI_Event;
event.subtype = sev.wheel.y > 0 ? EV_GUI_WheelUp : EV_GUI_WheelDown;
if (sev.wheel.y == 0)
event.subtype = sev.wheel.x > 0 ? EV_GUI_WheelRight : EV_GUI_WheelLeft;
else
event.subtype = sev.wheel.y > 0 ? EV_GUI_WheelUp : EV_GUI_WheelDown;
SDL_Keymod kmod = SDL_GetModState();
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
((kmod & KMOD_ALT) ? GKM_ALT : 0);
D_PostEvent (&event);
}
else

View file

@ -56,6 +56,7 @@
#include "doomerrors.h"
#include "i_system.h"
#include "g_game.h"
#include "atterm.h"
// MACROS ------------------------------------------------------------------
@ -89,47 +90,9 @@ FArgs *Args;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static void (*TermFuncs[MAX_TERMS]) ();
static const char *TermNames[MAX_TERMS];
static int NumTerms;
// CODE --------------------------------------------------------------------
void addterm (void (*func) (), const char *name)
{
// Make sure this function wasn't already registered.
for (int i = 0; i < NumTerms; ++i)
{
if (TermFuncs[i] == func)
{
return;
}
}
if (NumTerms == MAX_TERMS)
{
func ();
I_FatalError (
"Too many exit functions registered.\n"
"Increase MAX_TERMS in i_main.cpp");
}
TermNames[NumTerms] = name;
TermFuncs[NumTerms++] = func;
}
void popterm ()
{
if (NumTerms)
NumTerms--;
}
void call_terms ()
{
while (NumTerms > 0)
{
// printf ("term %d - %s\n", NumTerms, TermNames[NumTerms-1]);
TermFuncs[--NumTerms] ();
}
}
static void NewFailure ()
{

View file

@ -51,6 +51,7 @@
#include "d_net.h"
#include "g_game.h"
#include "c_dispatch.h"
#include "atterm.h"
#include "gameconfigfile.h"

View file

@ -42,6 +42,7 @@
#include "doomdef.h"
#include "i_system.h"
#include "c_cvars.h"
#include "atterm.h"
// MACROS ------------------------------------------------------------------

View file

@ -388,7 +388,7 @@ void FOBJModel::BuildVertexBuffer(FModelRenderer *renderer)
side + j * 3 + // Current surface and previous triangles
surfaces[i].vbStart; // Previous surfaces
OBJFaceSide &curSide = surfaces[i].tris[j].sides[side];
OBJFaceSide &curSide = surfaces[i].tris[j].sides[2 - side];
int vidx = curSide.vertref;
int uvidx = (curSide.uvref >= 0 && (unsigned int)curSide.uvref < uvs.Size()) ? curSide.uvref : 0;

View file

@ -64,6 +64,7 @@
#include "actorinlines.h"
#include "g_game.h"
#include "i_system.h"
#include "atterm.h"
// EXTERNAL DATA DECLARATIONS ----------------------------------------------

View file

@ -35,13 +35,61 @@
EXTERN_CVAR(Float, transsouls)
IMPLEMENT_CLASS(DShape2DTransform, false, false)
DEFINE_ACTION_FUNCTION(DShape2DTransform, Clear)
{
PARAM_SELF_PROLOGUE(DShape2DTransform);
self->transform.Identity();
return 0;
}
DEFINE_ACTION_FUNCTION(DShape2DTransform, Rotate)
{
PARAM_SELF_PROLOGUE(DShape2DTransform);
PARAM_FLOAT(angle);
self->transform = DMatrix3x3::Rotate2D(DEG2RAD(angle)) * self->transform;
return 0;
}
DEFINE_ACTION_FUNCTION(DShape2DTransform, Scale)
{
PARAM_SELF_PROLOGUE(DShape2DTransform);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
self->transform = DMatrix3x3::Scale2D(DVector2(x, y)) * self->transform;
return 0;
}
DEFINE_ACTION_FUNCTION(DShape2DTransform, Translate)
{
PARAM_SELF_PROLOGUE(DShape2DTransform);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
self->transform = DMatrix3x3::Translate2D(DVector2(x, y)) * self->transform;
return 0;
}
IMPLEMENT_CLASS(DShape2D, false, false)
DEFINE_ACTION_FUNCTION(DShape2D, SetTransform)
{
PARAM_SELF_PROLOGUE(DShape2D);
PARAM_OBJECT(transform, DShape2DTransform);
self->transform = transform->transform;
self->dirty = true;
return 0;
}
DEFINE_ACTION_FUNCTION(DShape2D, Clear)
{
PARAM_SELF_PROLOGUE(DShape2D);
PARAM_INT(which);
if ( which&C_Verts ) self->mVertices.Clear();
if ( which&C_Verts )
{
self->mVertices.Clear();
self->dirty = true;
}
if ( which&C_Coords ) self->mCoords.Clear();
if ( which&C_Indices ) self->mIndices.Clear();
return 0;
@ -53,6 +101,7 @@ DEFINE_ACTION_FUNCTION(DShape2D, PushVertex)
PARAM_FLOAT(x);
PARAM_FLOAT(y);
self->mVertices.Push(DVector2(x,y));
self->dirty = true;
return 0;
}
@ -380,13 +429,22 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
if (!img->isHardwareCanvas() && parms.remap != nullptr && !parms.remap->Inactive)
dg.mTranslation = parms.remap;
if (shape->dirty) {
if (shape->mVertices.Size() != shape->mTransformedVertices.Size())
shape->mTransformedVertices.Resize(shape->mVertices.Size());
for (int i = 0; i < dg.mVertCount; i++) {
shape->mTransformedVertices[i] = (shape->transform * DVector3(shape->mVertices[i], 1.0)).XY();
}
shape->dirty = false;
}
double minx = 16383, miny = 16383, maxx = -16384, maxy = -16384;
for ( int i=0; i<dg.mVertCount; i++ )
{
if ( shape->mVertices[i].X < minx ) minx = shape->mVertices[i].X;
if ( shape->mVertices[i].Y < miny ) miny = shape->mVertices[i].Y;
if ( shape->mVertices[i].X > maxx ) maxx = shape->mVertices[i].X;
if ( shape->mVertices[i].Y > maxy ) maxy = shape->mVertices[i].Y;
if ( shape->mTransformedVertices[i].X < minx ) minx = shape->mTransformedVertices[i].X;
if ( shape->mTransformedVertices[i].Y < miny ) miny = shape->mTransformedVertices[i].Y;
if ( shape->mTransformedVertices[i].X > maxx ) maxx = shape->mTransformedVertices[i].X;
if ( shape->mTransformedVertices[i].Y > maxy ) maxy = shape->mTransformedVertices[i].Y;
}
if (minx < (double)parms.lclip || miny < (double)parms.uclip || maxx >(double)parms.rclip || maxy >(double)parms.dclip)
{
@ -402,7 +460,7 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
dg.mVertIndex = (int)mVertices.Reserve(dg.mVertCount);
TwoDVertex *ptr = &mVertices[dg.mVertIndex];
for ( int i=0; i<dg.mVertCount; i++ )
ptr[i].Set(shape->mVertices[i].X, shape->mVertices[i].Y, 0, shape->mCoords[i].X, shape->mCoords[i].Y, vertexcolor);
ptr[i].Set(shape->mTransformedVertices[i].X, shape->mTransformedVertices[i].Y, 0, shape->mCoords[i].X, shape->mCoords[i].Y, vertexcolor);
dg.mIndexIndex = mIndices.Size();
dg.mIndexCount += shape->mIndices.Size();
for ( int i=0; i<int(shape->mIndices.Size()); i+=3 )
@ -485,10 +543,10 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0);
}
poly.mIndexIndex = mIndices.Size();
poly.mIndexCount += (npoints - 2) * 3;
if (indices == nullptr || indexcount == 0)
{
poly.mIndexCount += (npoints - 2) * 3;
for (int i = 2; i < npoints; ++i)
{
AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
@ -496,10 +554,11 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
}
else
{
poly.mIndexCount += (int)indexcount;
int addr = mIndices.Reserve(indexcount);
for (size_t i = 0; i < indexcount; i++)
{
mIndices[addr + i] = addr + indices[i];
mIndices[addr + i] = poly.mVertIndex + indices[i];
}
}

View file

@ -9,6 +9,18 @@
struct DrawParms;
class DShape2DTransform : public DObject
{
DECLARE_CLASS(DShape2DTransform, DObject)
public:
DShape2DTransform()
{
transform.Identity();
}
DMatrix3x3 transform;
};
// intermediate struct for shape drawing
enum EClearWhich
@ -23,9 +35,21 @@ class DShape2D : public DObject
DECLARE_CLASS(DShape2D,DObject)
public:
DShape2D()
{
transform.Identity();
}
TArray<int> mIndices;
TArray<DVector2> mVertices;
TArray<DVector2> mCoords;
DMatrix3x3 transform;
// dirty stores whether we need to re-apply the transformation
// otherwise it uses the cached values
bool dirty = true;
TArray<DVector2> mTransformedVertices;
};
class F2DDrawer

View file

@ -235,7 +235,8 @@ void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma)
}
mPresentShader->Uniforms->Scale = { screen->mScreenViewport.width / (float)mBuffers->GetWidth(), screen->mScreenViewport.height / (float)mBuffers->GetHeight() };
mPresentShader->Uniforms->Offset = { 0.0f, 0.0f };
mPresentShader->Uniforms.Set();
mPresentShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresentShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}

View file

@ -34,6 +34,7 @@
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/shaders/gl_shaderprogram.h"
#include "gl/system/gl_buffers.h"
#include <random>
CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
@ -955,7 +956,7 @@ void GLPPRenderState::Draw()
if (!shader->Uniforms)
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false, false));
shader->Uniforms->SetData(Uniforms.Data.Size(), Uniforms.Data.Data());
shader->Uniforms->BindBase();
static_cast<GLDataBuffer*>(shader->Uniforms.get())->BindBase();
}
// Set shader

View file

@ -58,6 +58,7 @@
#include "r_videoscale.h"
#include "r_data/models/models.h"
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/system/gl_buffers.h"
EXTERN_CVAR(Int, screenblocks)
EXTERN_CVAR(Bool, cl_capfps)
@ -191,12 +192,17 @@ void FGLRenderer::UpdateShadowMap()
FGLPostProcessState savedState;
static_cast<GLDataBuffer*>(screen->mShadowMap.mLightList)->BindBase();
static_cast<GLDataBuffer*>(screen->mShadowMap.mNodesBuffer)->BindBase();
static_cast<GLDataBuffer*>(screen->mShadowMap.mLinesBuffer)->BindBase();
mBuffers->BindShadowMapFB();
mShadowMapShader->Bind();
mShadowMapShader->Uniforms->ShadowmapQuality = gl_shadowmap_quality;
mShadowMapShader->Uniforms->NodesCount = screen->mShadowMap.NodesCount();
mShadowMapShader->Uniforms.Set();
mShadowMapShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mShadowMapShader->Uniforms.GetBuffer())->BindBase();
glViewport(0, 0, gl_shadowmap_quality, 1024);
RenderScreenQuad();

View file

@ -27,7 +27,7 @@ class FGLRenderBuffers;
class FGL2DDrawer;
class FHardwareTexture;
class SWSceneDrawer;
class GLViewpointBuffer;
class HWViewpointBuffer;
struct FRenderViewpoint;
namespace OpenGLRenderer

View file

@ -189,9 +189,21 @@ bool FGLRenderState::ApplyShader()
matrixToGL(identityMatrix, activeShader->normalmodelmatrix_index);
}
auto index = screen->mLights->BindUBO(mLightIndex);
activeShader->muLightIndex.Set(index);
int index = mLightIndex;
// Mess alert for crappy AncientGL!
if (!screen->mLights->GetBufferType() && index >= 0)
{
size_t start, size;
index = screen->mLights->GetBinding(index, &start, &size);
if (start != mLastMappedLightIndex)
{
mLastMappedLightIndex = start;
static_cast<GLDataBuffer*>(screen->mLights->GetBuffer())->BindRange(nullptr, start, size);
}
}
activeShader->muLightIndex.Set(index);
return true;
}

View file

@ -68,6 +68,7 @@ class FGLRenderState : public FRenderState
int lastClamp = 0;
int lastTranslation = 0;
int maxBoundMaterial = -1;
size_t mLastMappedLightIndex = SIZE_MAX;
IVertexBuffer *mCurrentVertexBuffer;
int mCurrentVertexOffsets[2]; // one per binding point

View file

@ -57,6 +57,7 @@
#include "hwrenderer/scene/hw_portal.h"
#include "hwrenderer/utility/hw_vrmodes.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/system/gl_buffers.h"
//==========================================================================
//

View file

@ -33,6 +33,7 @@
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/shaders/gl_shaderprogram.h"
#include "gl/system/gl_buffers.h"
#include "menu/menu.h"
EXTERN_CVAR(Int, vr_mode)
@ -174,7 +175,8 @@ void FGLRenderer::prepareInterleavedPresent(FPresentShaderBase& shader)
screen->mScreenViewport.height / (float)mBuffers->GetHeight()
};
shader.Uniforms->Offset = { 0.0f, 0.0f };
shader.Uniforms.Set();
shader.Uniforms.SetData();
static_cast<GLDataBuffer*>(shader.Uniforms.GetBuffer())->BindBase();
}
//==========================================================================
@ -198,7 +200,8 @@ void FGLRenderer::PresentColumnInterleaved()
int windowHOffset = 0;
mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset;
mPresent3dColumnShader->Uniforms.Set();
mPresent3dColumnShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dColumnShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}
@ -225,7 +228,8 @@ void FGLRenderer::PresentRowInterleaved()
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2;
mPresent3dRowShader->Uniforms.Set();
mPresent3dRowShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dRowShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}
@ -256,7 +260,8 @@ void FGLRenderer::PresentCheckerInterleaved()
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2; // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
mPresent3dCheckerShader->Uniforms.Set();
mPresent3dCheckerShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dCheckerShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}

View file

@ -210,10 +210,9 @@ void GLVertexBuffer::Bind(int *offsets)
}
}
void GLDataBuffer::BindRange(size_t start, size_t length)
void GLDataBuffer::BindRange(FRenderState *state, size_t start, size_t length)
{
if (mUseType == GL_UNIFORM_BUFFER) // SSBO's cannot be rebound.
glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length);
glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length);
}
void GLDataBuffer::BindBase()

View file

@ -66,8 +66,8 @@ class GLDataBuffer : public IDataBuffer, public GLBuffer
int mBindingPoint;
public:
GLDataBuffer(int bindingpoint, bool is_ssbo) : GLBuffer(is_ssbo? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER), mBindingPoint(bindingpoint) {}
void BindRange(size_t start, size_t length) override;
void BindBase() override;
void BindRange(FRenderState* state, size_t start, size_t length);
void BindBase();
};
}

View file

@ -126,7 +126,7 @@ void OpenGLFrameBuffer::InitializeState()
glslversion = gl.glslversion;
uniformblockalignment = gl.uniformblockalignment;
maxuniformblock = gl.maxuniformblock;
gl_vendorstring = gl.vendorstring;
vendorstring = gl.vendorstring;
if (first)
{
@ -154,12 +154,14 @@ void OpenGLFrameBuffer::InitializeState()
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
mSkyData = new FSkyVertexBuffer;
mViewpoints = new GLViewpointBuffer;
mViewpoints = new HWViewpointBuffer;
mLights = new FLightBuffer();
GLRenderer = new FGLRenderer(this);
GLRenderer->Initialize(GetWidth(), GetHeight());
static_cast<GLDataBuffer*>(mLights->GetBuffer())->BindBase();
mDebug = std::make_shared<FGLDebug>();
mDebug->Update();
}

View file

@ -177,7 +177,7 @@ void gl_LoadExtensions()
// Mesa implements shader storage only for fragment shaders.
// Just disable the feature there. The light buffer may just use a uniform buffer without any adverse effects.
int v;
int v = 0;
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &v);
if (v == 0)
gl.flags &= ~RFL_SHADER_STORAGE_BUFFER;

View file

@ -3,6 +3,8 @@
#include <stddef.h>
#include <assert.h>
class FRenderState;
// The low level code needs to know which attributes exist.
// OpenGL needs to change the state of all of them per buffer binding.
// VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want.
@ -76,7 +78,6 @@ class IDataBuffer : virtual public IBuffer
{
// Can be either uniform or shader storage buffer, depending on its needs.
public:
virtual void BindRange(size_t start, size_t length) = 0;
virtual void BindBase() = 0;
virtual void BindRange(FRenderState *state, size_t start, size_t length) = 0;
};

View file

@ -33,7 +33,7 @@
static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough
GLViewpointBuffer::GLViewpointBuffer()
HWViewpointBuffer::HWViewpointBuffer()
{
mBufferSize = INITIAL_BUFFER_SIZE;
mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment;
@ -45,13 +45,13 @@ GLViewpointBuffer::GLViewpointBuffer()
mClipPlaneInfo.Push(0);
}
GLViewpointBuffer::~GLViewpointBuffer()
HWViewpointBuffer::~HWViewpointBuffer()
{
delete mBuffer;
}
void GLViewpointBuffer::CheckSize()
void HWViewpointBuffer::CheckSize()
{
if (mUploadIndex >= mBufferSize)
{
@ -62,18 +62,18 @@ void GLViewpointBuffer::CheckSize()
}
}
int GLViewpointBuffer::Bind(FRenderState &di, unsigned int index)
int HWViewpointBuffer::Bind(FRenderState &di, unsigned int index)
{
if (index != mLastMappedIndex)
{
mLastMappedIndex = index;
mBuffer->BindRange(index * mBlockAlign, mBlockAlign);
mBuffer->BindRange(&di, index * mBlockAlign, mBlockAlign);
di.EnableClipDistance(0, mClipPlaneInfo[index]);
}
return index;
}
void GLViewpointBuffer::Set2D(FRenderState &di, int width, int height)
void HWViewpointBuffer::Set2D(FRenderState &di, int width, int height)
{
if (width != m2DWidth || height != m2DHeight)
{
@ -91,7 +91,7 @@ void GLViewpointBuffer::Set2D(FRenderState &di, int width, int height)
Bind(di, 0);
}
int GLViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
int HWViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
{
CheckSize();
mBuffer->Map();
@ -102,7 +102,7 @@ int GLViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
return Bind(di, mUploadIndex++);
}
void GLViewpointBuffer::Clear()
void HWViewpointBuffer::Clear()
{
// Index 0 is reserved for the 2D projection.
mUploadIndex = 1;

View file

@ -5,7 +5,7 @@
struct HWViewpointUniforms;
class FRenderState;
class GLViewpointBuffer
class HWViewpointBuffer
{
IDataBuffer *mBuffer;
@ -24,8 +24,8 @@ class GLViewpointBuffer
public:
GLViewpointBuffer();
~GLViewpointBuffer();
HWViewpointBuffer();
~HWViewpointBuffer();
void Clear();
int Bind(FRenderState &di, unsigned int index);
void Set2D(FRenderState &di, int width, int height);

View file

@ -126,14 +126,16 @@ public:
mBuffer = screen->CreateDataBuffer(bindingpoint, false, false);
}
void Set(bool bind = true)
void SetData()
{
if (mBuffer != nullptr)
mBuffer->SetData(sizeof(T), &Values);
}
// Let's hope this can be done better when things have moved further ahead.
// This really is not the best place to add something that depends on API behavior.
if (bind) mBuffer->BindBase();
IDataBuffer* GetBuffer() const
{
// OpenGL needs to mess around with this in ways that should not be part of the interface.
return mBuffer;
}
T *operator->() { return &Values; }

View file

@ -44,7 +44,7 @@ FLightBuffer::FLightBuffer()
// Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs.
// We only want to disable using SSBOs for lights but not disable the feature entirely.
// Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD.
if (screen->IsVulkan() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->gl_vendorstring, "Intel")))
if (screen->IsVulkan() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->vendorstring, "Intel")))
{
mBufferType = true;
mBlockAlign = 0;
@ -74,7 +74,6 @@ FLightBuffer::~FLightBuffer()
void FLightBuffer::Clear()
{
mIndex = 0;
mLastMappedIndex = UINT_MAX;
}
int FLightBuffer::UploadLights(FDynLightData &data)
@ -127,16 +126,13 @@ int FLightBuffer::UploadLights(FDynLightData &data)
}
}
int FLightBuffer::DoBindUBO(unsigned int index)
int FLightBuffer::GetBinding(unsigned int index, size_t* pOffset, size_t* pSize)
{
// this function will only get called if a uniform buffer is used. For a shader storage buffer we only need to bind the buffer once at the start.
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
if (offset != mLastMappedIndex)
{
mLastMappedIndex = offset;
mBuffer->BindRange(offset * ELEMENT_SIZE, mBlockSize * ELEMENT_SIZE);
}
*pOffset = offset * ELEMENT_SIZE;
*pSize = mBlockSize * ELEMENT_SIZE;
return (index - offset);
}

View file

@ -15,7 +15,6 @@ class FLightBuffer
bool mBufferType;
std::atomic<unsigned int> mIndex;
unsigned int mLastMappedIndex;
unsigned int mBlockAlign;
unsigned int mBlockSize;
unsigned int mBufferSize;
@ -34,32 +33,12 @@ public:
void Unmap() { mBuffer->Unmap(); }
unsigned int GetBlockSize() const { return mBlockSize; }
bool GetBufferType() const { return mBufferType; }
int GetBinding(unsigned int index, size_t* pOffset, size_t* pSize);
int DoBindUBO(unsigned int index);
int ShaderIndex(unsigned int index) const
{
if (mBlockAlign == 0) return index;
// This must match the math in BindUBO.
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
return int(index-offset);
}
// Only relevant for OpenGL, so this does not need access to the render state.
int BindUBO(int index)
// OpenGL needs the buffer to mess around with the binding.
IDataBuffer* GetBuffer() const
{
if (!mBufferType && index > -1)
{
index = DoBindUBO(index);
}
return index;
}
// The parameter is a reminder for Vulkan.
void BindBase()
{
mBuffer->BindBase();
mLastMappedIndex = UINT_MAX;
return mBuffer;
}
};

View file

@ -176,9 +176,6 @@ bool IShadowMap::PerformUpdate()
UpdateCycles.Clock();
UploadAABBTree();
UploadLights();
mLightList->BindBase();
mNodesBuffer->BindBase();
mLinesBuffer->BindBase();
return true;
}
return false;

View file

@ -65,6 +65,8 @@ protected:
IShadowMap &operator=(IShadowMap &) = delete;
// OpenGL storage buffer with the list of lights in the shadow map texture
// These buffers need to be accessed by the OpenGL backend directly so that they can be bound.
public:
IDataBuffer *mLightList = nullptr;
// OpenGL storage buffers for the AABB tree

View file

@ -468,7 +468,6 @@ void HWDrawInfo::RenderScene(FRenderState &state)
state.SetDepthMask(true);
screen->mLights->BindBase();
state.EnableFog(true);
state.SetRenderStyle(STYLE_Source);

View file

@ -55,6 +55,7 @@
#include "templates.h"
#include "r_utility.h"
#include "r_renderer.h"
#include "atterm.h"
#include <atomic>
FDynamicColormap NormalLight;

View file

@ -35,7 +35,7 @@ void VkPostprocess::SetActiveRenderTarget()
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
imageTransition.execute(fb->GetDrawCommands());
fb->GetRenderState()->SetRenderTarget(buffers->PipelineImage[mCurrentPipelineImage].View.get(), nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
}
void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
@ -402,6 +402,18 @@ VkPPTexture::VkPPTexture(PPTexture *texture)
}
}
VkPPTexture::~VkPPTexture()
{
if (auto fb = GetVulkanFrameBuffer())
{
if (TexImage.Image) fb->FrameDeleteList.Images.push_back(std::move(TexImage.Image));
if (TexImage.View) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.View));
if (TexImage.DepthOnlyView) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.DepthOnlyView));
if (TexImage.PPFramebuffer) fb->FrameDeleteList.Framebuffers.push_back(std::move(TexImage.PPFramebuffer));
if (Staging) fb->FrameDeleteList.Buffers.push_back(std::move(Staging));
}
}
/////////////////////////////////////////////////////////////////////////////
VkPPShader::VkPPShader(PPShader *shader)
@ -585,6 +597,7 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
VkTextureImage *tex = GetTexture(output.Type, output.Texture);
VkImageView view;
std::unique_ptr<VulkanFramebuffer> *framebufferptr = nullptr;
int w, h;
if (tex)
{
@ -597,15 +610,17 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
view = tex->View->view;
w = tex->Image->width;
h = tex->Image->height;
framebufferptr = &tex->PPFramebuffer;
}
else
{
view = fb->swapChain->swapChainImageViews[fb->presentImageIndex];
framebufferptr = &fb->swapChain->framebuffers[fb->presentImageIndex];
w = fb->swapChain->actualExtent.width;
h = fb->swapChain->actualExtent.height;
}
auto &framebuffer = passSetup->Framebuffers[view];
auto &framebuffer = *framebufferptr;
if (!framebuffer)
{
FramebufferBuilder builder;

View file

@ -88,6 +88,7 @@ class VkPPTexture : public PPTextureBackend
{
public:
VkPPTexture(PPTexture *texture);
~VkPPTexture();
VkTextureImage TexImage;
std::unique_ptr<VulkanBuffer> Staging;
@ -103,7 +104,6 @@ public:
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
std::unique_ptr<VulkanRenderPass> RenderPass;
std::unique_ptr<VulkanPipeline> Pipeline;
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffers;
private:
void CreateDescriptorLayout(const VkPPRenderPassKey &key);

View file

@ -59,7 +59,6 @@ public:
VkRenderPassKey PassKey;
std::unique_ptr<VulkanRenderPass> RenderPasses[8];
std::map<VkPipelineKey, std::unique_ptr<VulkanPipeline>> Pipelines;
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffer;
private:
std::unique_ptr<VulkanRenderPass> CreateRenderPass(int clearTargets);

View file

@ -528,11 +528,11 @@ void VkRenderState::EnableDrawBuffers(int count)
}
}
void VkRenderState::SetRenderTarget(VulkanImageView *view, VulkanImageView *depthStencilView, int width, int height, VkFormat format, VkSampleCountFlagBits samples)
void VkRenderState::SetRenderTarget(VkTextureImage *image, VulkanImageView *depthStencilView, int width, int height, VkFormat format, VkSampleCountFlagBits samples)
{
EndRenderPass();
mRenderTarget.View = view;
mRenderTarget.Image = image;
mRenderTarget.DepthStencil = depthStencilView;
mRenderTarget.Width = width;
mRenderTarget.Height = height;
@ -552,14 +552,14 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer)
mPassSetup = fb->GetRenderPassManager()->GetRenderPass(key);
auto &framebuffer = mPassSetup->Framebuffer[mRenderTarget.View->view];
auto &framebuffer = mRenderTarget.Image->RSFramebuffers[key];
if (!framebuffer)
{
auto buffers = fb->GetBuffers();
FramebufferBuilder builder;
builder.setRenderPass(mPassSetup->GetRenderPass(0));
builder.setSize(mRenderTarget.Width, mRenderTarget.Height);
builder.addAttachment(mRenderTarget.View);
builder.addAttachment(mRenderTarget.Image->View.get());
if (key.DrawBuffers > 1)
builder.addAttachment(buffers->SceneFog.View.get());
if (key.DrawBuffers > 2)

View file

@ -12,6 +12,7 @@
#include "hwrenderer/textures/hw_material.h"
class VkRenderPassSetup;
class VkTextureImage;
class VkRenderState : public FRenderState
{
@ -43,7 +44,7 @@ public:
void EnableDrawBuffers(int count) override;
void BeginFrame();
void SetRenderTarget(VulkanImageView *view, VulkanImageView *depthStencilView, int width, int height, VkFormat Format, VkSampleCountFlagBits samples);
void SetRenderTarget(VkTextureImage *image, VulkanImageView *depthStencilView, int width, int height, VkFormat Format, VkSampleCountFlagBits samples);
void Bind(int bindingpoint, uint32_t offset);
void EndRenderPass();
void EndFrame();
@ -112,7 +113,7 @@ protected:
struct RenderTarget
{
VulkanImageView *View = nullptr;
VkTextureImage *Image = nullptr;
VulkanImageView *DepthStencil = nullptr;
int Width = 0;
int Height = 0;

View file

@ -204,12 +204,9 @@ void VKVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t s
/////////////////////////////////////////////////////////////////////////////
void VKDataBuffer::BindRange(size_t start, size_t length)
void VKDataBuffer::BindRange(FRenderState* state, size_t start, size_t length)
{
GetVulkanFrameBuffer()->GetRenderState()->Bind(bindingpoint, (uint32_t)start);
static_cast<VkRenderState*>(state)->Bind(bindingpoint, (uint32_t)start);
}
void VKDataBuffer::BindBase()
{
GetVulkanFrameBuffer()->GetRenderState()->Bind(bindingpoint, 0);
}

View file

@ -68,8 +68,7 @@ public:
}
}
void BindRange(size_t start, size_t length) override;
void BindBase() override;
void BindRange(FRenderState *state, size_t start, size_t length) override;
int bindingpoint;
};

View file

@ -128,7 +128,14 @@ void VulkanFrameBuffer::InitializeState()
first = false;
}
gl_vendorstring = "Vulkan";
switch (device->PhysicalDevice.Properties.vendorID)
{
case 0x1002: vendorstring = "AMD"; break;
case 0x10DE: vendorstring = "NVIDIA"; break;
case 0x8086: vendorstring = "Intel"; break;
default: vendorstring = "Unknown"; break;
}
hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
glslversion = 4.50f;
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment;
@ -145,7 +152,7 @@ void VulkanFrameBuffer::InitializeState()
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
mSkyData = new FSkyVertexBuffer;
mViewpoints = new GLViewpointBuffer;
mViewpoints = new HWViewpointBuffer;
mLights = new FLightBuffer();
CreateFanToTrisIndexBuffer();
@ -199,6 +206,7 @@ void VulkanFrameBuffer::DeleteFrameObjects()
{
FrameDeleteList.Images.clear();
FrameDeleteList.ImageViews.clear();
FrameDeleteList.Framebuffers.clear();
FrameDeleteList.Buffers.clear();
FrameDeleteList.Descriptors.clear();
FrameDeleteList.DescriptorPools.clear();
@ -444,7 +452,7 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor *
if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao
{
mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
bool useSSAO = (gl_ssao != 0);
GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount());
@ -514,7 +522,7 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint
barrier0.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier0.execute(GetDrawCommands());
mRenderState->SetRenderTarget(image->View.get(), depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT);
mRenderState->SetRenderTarget(image, depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT);
IntRect bounds;
bounds.left = bounds.top = 0;
@ -530,7 +538,7 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint
barrier1.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
barrier1.execute(GetDrawCommands());
mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
tex->SetUpdated(true);
}
@ -709,11 +717,12 @@ void VulkanFrameBuffer::UpdatePalette()
FTexture *VulkanFrameBuffer::WipeStartScreen()
{
const auto &viewport = screen->mScreenViewport;
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
SetViewportRects(nullptr);
auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1);
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeStartScreen");
systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeStartScreen");
return tex;
}
@ -724,11 +733,10 @@ FTexture *VulkanFrameBuffer::WipeEndScreen()
Draw2D();
Clear2D();
const auto &viewport = screen->mScreenViewport;
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1);
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeEndScreen");
systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeEndScreen");
return tex;
}

View file

@ -57,6 +57,7 @@ public:
public:
std::vector<std::unique_ptr<VulkanImage>> Images;
std::vector<std::unique_ptr<VulkanImageView>> ImageViews;
std::vector<std::unique_ptr<VulkanFramebuffer>> Framebuffers;
std::vector<std::unique_ptr<VulkanBuffer>> Buffers;
std::vector<std::unique_ptr<VulkanDescriptorSet>> Descriptors;
std::vector<std::unique_ptr<VulkanDescriptorPool>> DescriptorPools;

View file

@ -207,6 +207,7 @@ bool VulkanSwapChain::CreateSwapChain(VkSwapchainKHR oldSwapChain)
void VulkanSwapChain::CreateViews()
{
framebuffers.resize(swapChainImages.size());
swapChainImageViews.reserve(swapChainImages.size());
for (size_t i = 0; i < swapChainImages.size(); i++)
{
@ -335,6 +336,7 @@ void VulkanSwapChain::GetImages()
void VulkanSwapChain::ReleaseViews()
{
framebuffers.clear();
for (auto &view : swapChainImageViews)
{
vkDestroyImageView(device->device, view, nullptr);

View file

@ -4,6 +4,7 @@
class VulkanSemaphore;
class VulkanFence;
class VulkanFramebuffer;
class VulkanSwapChain
{
@ -22,6 +23,7 @@ public:
std::vector<VkImage> swapChainImages;
std::vector<VkImageView> swapChainImageViews;
std::vector<std::unique_ptr<VulkanFramebuffer>> framebuffers;
VkExtent2D actualExtent;

View file

@ -72,8 +72,10 @@ void VkHardwareTexture::Reset()
auto &deleteList = fb->FrameDeleteList;
if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image));
if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View));
for (auto &it : mImage.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second));
if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image));
if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View));
for (auto &it : mDepthStencil.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second));
mImage.reset();
mDepthStencil.reset();
}
@ -374,5 +376,33 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name)
mImage.View = viewbuilder.create(fb->device);
mImage.View->SetDebugName(name);
fb->GetPostprocess()->BlitCurrentToImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if (fb->GetBuffers()->GetWidth() > 0 && fb->GetBuffers()->GetHeight() > 0)
{
fb->GetPostprocess()->BlitCurrentToImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
else
{
// hwrenderer asked image data from a frame buffer that was never written into. Let's give it that..
// (ideally the hwrenderer wouldn't do this, but the calling code is too complex for me to fix)
VkImageTransition transition0;
transition0.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
transition0.execute(fb->GetTransferCommands());
VkImageSubresourceRange range = {};
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
range.layerCount = 1;
range.levelCount = 1;
VkClearColorValue value = {};
value.float32[0] = 0.0f;
value.float32[1] = 0.0f;
value.float32[2] = 0.0f;
value.float32[3] = 1.0f;
fb->GetTransferCommands()->clearColorImage(mImage.Image->image, mImage.Layout, &value, 1, &range);
VkImageTransition transition1;
transition1.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
transition1.execute(fb->GetTransferCommands());
}
}

View file

@ -3,6 +3,7 @@
#include "vulkan/system/vk_objects.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/renderer/vk_renderpass.h"
class VkTextureImage
{
@ -23,6 +24,8 @@ public:
std::unique_ptr<VulkanImageView> DepthOnlyView;
VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
std::unique_ptr<VulkanFramebuffer> PPFramebuffer;
std::map<VkRenderPassKey, std::unique_ptr<VulkanFramebuffer>> RSFramebuffers;
};
class VkImageTransition

View file

@ -48,6 +48,7 @@
#include "r_data/sprites.h"
#include "vm.h"
#include "i_system.h"
#include "atterm.h"
// MACROS ------------------------------------------------------------------

View file

@ -46,6 +46,7 @@
#include "vm.h"
#include "dobject.h"
#include "menu/menu.h"
#include "atterm.h"

View file

@ -83,6 +83,7 @@
#include "g_levellocals.h"
#include "vm.h"
#include "g_game.h"
#include "atterm.h"
// MACROS ------------------------------------------------------------------

View file

@ -82,6 +82,8 @@ static const FLOP FxFlops[] =
{ NAME_CosH, FLOP_COSH, [](double v) { return g_cosh(v); } },
{ NAME_SinH, FLOP_SINH, [](double v) { return g_sinh(v); } },
{ NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(v); } },
{ NAME_Round, FLOP_ROUND, [](double v) { return round(v); } },
};
@ -4835,7 +4837,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
// If this is a local variable we need another register for the result.
if (trueop.Fixed)
{
out = ExpEmit(build, trueop.RegType);
out = ExpEmit(build, trueop.RegType, trueop.RegCount);
build->Emit(truex->ValueType->GetMoveOp(), out.RegNum, trueop.RegNum, 0);
}
else out = trueop;
@ -6127,18 +6129,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
{
if (sym->mVersion <= ctx.Version)
{
if (!(ctx.Function->Variants[0].Flags & VARF_Deprecated) && Wads.GetLumpFile(ctx.Lump) == 0)
{
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated global variable %s - deprecated since %d.%d.%d", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision);
}
else
{
// Allow use of deprecated symbols in deprecated functions of the internal code. This is meant to allow deprecated code to remain as it was,
// even if it depends on some deprecated symbol.
// The main motivation here is to keep the deprecated static functions accessing the global level variable as they were.
// Print these only if debug output is active and at the highest verbosity level.
ScriptPosition.Message(MSG_DEBUGMSG, TEXTCOLOR_BLUE "Accessing deprecated global variable %s - deprecated since %d.%d.%d", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision);
}
// Allow use of deprecated symbols in deprecated functions of the internal code. This is meant to allow deprecated code to remain as it was,
// even if it depends on some deprecated symbol.
// The main motivation here is to keep the deprecated static functions accessing the global level variable as they were.
// Print these only if debug output is active and at the highest verbosity level.
const bool internal = (ctx.Function->Variants[0].Flags & VARF_Deprecated) && Wads.GetLumpFile(ctx.Lump) == 0;
ScriptPosition.Message(internal ? MSG_DEBUGMSG : MSG_WARNING,
"%sAccessing deprecated global variable %s - deprecated since %d.%d.%d", internal ? TEXTCOLOR_BLUE : "",
sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision);
}
}
@ -7425,7 +7424,6 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
{
bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta;
arrayvar.Free(build);
start = ExpEmit(build, REGT_POINTER);
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
@ -7445,18 +7443,18 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
arraymemberbase->membervar = origmembervar;
arraymemberbase->AddressRequested = origaddrreq;
Array->ValueType = origvaluetype;
arrayvar.Free(build);
}
else if (Array->ExprType == EFX_ArrayElement && Array->isStaticArray())
{
bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta;
bound = ExpEmit(build, REGT_INT);
build->Emit(OP_LW, bound.RegNum, arrayvar.RegNum, build->GetConstantInt(myoffsetof(FArray, Count)));
arrayvar.Free(build);
start = ExpEmit(build, REGT_POINTER);
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
bound = ExpEmit(build, REGT_INT);
build->Emit(OP_LW, bound.RegNum, arrayvar.RegNum, build->GetConstantInt(sizeof(void*)));
nestedarray = true;
}
else start = arrayvar;
@ -7514,7 +7512,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
else
{
ExpEmit indexv(index->Emit(build));
if (SizeAddr != ~0u)
if (SizeAddr != ~0u || nestedarray)
{
build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum);
bound.Free(build);
@ -11352,8 +11350,59 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
{
if (RegNum == -1)
{
if (!(VarFlags & VARF_Out)) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount);
else RegNum = build->Registers[REGT_POINTER].Get(1);
if (!(VarFlags & VARF_Out))
{
const int regType = ValueType->GetRegType();
assert(regType <= REGT_TYPE);
auto& registers = build->Registers[regType];
RegNum = registers.Get(RegCount);
// Check for reused registers and clean them if needed
bool useDirtyRegisters = false;
for (int reg = RegNum, end = RegNum + RegCount; reg < end; ++reg)
{
if (!registers.IsDirty(reg))
{
continue;
}
useDirtyRegisters = true;
switch (regType)
{
case REGT_INT:
build->Emit(OP_LI, reg, 0, 0);
break;
case REGT_FLOAT:
build->Emit(OP_LKF, reg, build->GetConstantFloat(0.0));
break;
case REGT_STRING:
build->Emit(OP_LKS, reg, build->GetConstantString(nullptr));
break;
case REGT_POINTER:
build->Emit(OP_LKP, reg, build->GetConstantAddress(nullptr));
break;
default:
assert(false);
break;
}
}
if (useDirtyRegisters)
{
ScriptPosition.Message(MSG_DEBUGMSG, "Implicit initialization of variable %s", Name.GetChars());
}
}
else
{
RegNum = build->Registers[REGT_POINTER].Get(1);
}
}
}
else

View file

@ -783,7 +783,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Find, ArrayFind<FDynArray_Obj COMMA
int ObjArrayPush(FDynArray_Obj *self, DObject *obj)
{
if (self == nullptr) NullParam("\"self\"");
GC::WriteBarrier(obj);
return self->Push(obj);
}
@ -812,7 +811,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Delete, ArrayDelete<FDynArray_Obj>)
void ObjArrayInsert(FDynArray_Obj *self,int index, DObject *obj)
{
if (self == nullptr) NullParam("\"self\"");
GC::WriteBarrier(obj);
self->Insert(index, obj);
}

View file

@ -367,6 +367,7 @@ void VMFunctionBuilder::ParamChange(int delta)
VMFunctionBuilder::RegAvailability::RegAvailability()
{
memset(Used, 0, sizeof(Used));
memset(Dirty, 0, sizeof(Dirty));
MostUsed = 0;
}
@ -493,16 +494,19 @@ void VMFunctionBuilder::RegAvailability::Return(int reg, int count)
// because for that case it pushes the self pointer a second time without reallocating, so it gets freed twice.
//assert((Used[firstword] & mask) == mask);
Used[firstword] &= ~mask;
Dirty[firstword] |= mask;
}
else
{ // Range is in two words.
partialmask = mask << firstbit;
assert((Used[firstword] & partialmask) == partialmask);
Used[firstword] &= ~partialmask;
Dirty[firstword] |= partialmask;
partialmask = mask >> (32 - firstbit);
assert((Used[firstword + 1] & partialmask) == partialmask);
Used[firstword + 1] &= ~partialmask;
Dirty[firstword + 1] |= partialmask;
}
}

View file

@ -37,8 +37,16 @@ public:
void Return(int reg, int count);
bool Reuse(int regnum);
bool IsDirty(int reg) const
{
const int firstword = reg / 32;
const int firstbit = reg & 31;
return Dirty[firstword] & (1 << firstbit);
}
private:
VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used)
VM_UWORD Dirty[256/32];
int MostUsed;
friend class VMFunctionBuilder;

View file

@ -181,6 +181,8 @@ static const char *const FlopNames[] =
"cosh",
"sinh",
"tanh",
"round",
};
static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const VMScriptFunction *func);

View file

@ -1148,6 +1148,7 @@ static void ParseActor(FScanner &sc, PNamespace *ns)
bag.Namespace = ns;
bag.Version = { 2, 0, 0 };
bag.fromDecorate = true;
bag.ScriptPosition = sc;
info = ParseActorHeader(sc, &bag);
sc.MustGetToken('{');
while (sc.MustGetAnyToken(), sc.TokenType != '}')

View file

@ -323,6 +323,28 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
I_Error("Native direct member function calls not implemented\n");
}
if (target->ImplicitArgs > 0)
{
auto label = EmitThrowExceptionLabel(X_READ_NIL);
assert(ParamOpcodes.Size() > 0);
const VMOP *param = ParamOpcodes[0];
const int bc = param->i16u;
asmjit::X86Gp *reg = nullptr;
switch (param->a & REGT_TYPE)
{
case REGT_STRING: reg = &regS[bc]; break;
case REGT_POINTER: reg = &regA[bc]; break;
default:
I_Error("Unexpected register type for self pointer\n");
break;
}
cc.test(*reg, *reg);
cc.jz(label);
}
asmjit::CBNode *cursorBefore = cc.getCursor();
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature());
call->setInlineComment(target->PrintableName.GetChars());

View file

@ -985,6 +985,7 @@ void JitCompiler::EmitFLOP()
case FLOP_COSH: func = g_cosh; break;
case FLOP_SINH: func = g_sinh; break;
case FLOP_TANH: func = g_tanh; break;
case FLOP_ROUND: func = round; break;
}
auto result = newResultXmmSd();

View file

@ -1741,6 +1741,8 @@ static double DoFLOP(int flop, double v)
case FLOP_COSH: return g_cosh(v);
case FLOP_SINH: return g_sinh(v);
case FLOP_TANH: return g_tanh(v);
case FLOP_ROUND: return round(v);
}
assert(0);
return 0;

View file

@ -101,6 +101,8 @@ enum
FLOP_COSH,
FLOP_SINH,
FLOP_TANH,
FLOP_ROUND,
};
// Cast operations

View file

@ -1353,7 +1353,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *
// This is a global variable.
if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32;
PField *f = Create<PField>(name->Name, thisfieldtype, varflags | VARF_Native | VARF_Static, fd->FieldOffset, fd->BitValue);
if (f->Flags & (ZCC_Version | ZCC_Deprecated))
if (field->Flags & (ZCC_Version | ZCC_Deprecated))
{
f->mVersion = field->Version;
}

View file

@ -933,7 +933,8 @@ void pre_resample(Sample * sp)
return;
}
dest = newdata = (sample_t *)safe_malloc((int32_t)(newlen >> (FRACTION_BITS - 1)) + 2);
// [EP] Fix the bad allocation count.
dest = newdata = (sample_t *)safe_malloc(((int32_t)(newlen >> (FRACTION_BITS - 1)) + 2)*sizeof(sample_t));
dest[newlen >> FRACTION_BITS] = 0;
*dest++ = src[0];

97
src/utility/atterm.cpp Normal file
View file

@ -0,0 +1,97 @@
/*
** attern.cpp
** Termination handling
**
**---------------------------------------------------------------------------
** Copyright 1998-2007 Randy Heit
** Copyright 2019 Christoph Oelckers
** 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.
**---------------------------------------------------------------------------
**
*/
#include <algorithm>
#include "tarray.h"
#include "atterm.h"
static TArray<std::pair<void (*)(void), const char *>> TermFuncs;
//==========================================================================
//
// atterm
//
// Our own atexit because atexit can be problematic under Linux, though I
// forget the circumstances that cause trouble.
//
//==========================================================================
void addterm(void (*func)(), const char *name)
{
// Make sure this function wasn't already registered.
for (auto &term : TermFuncs)
{
if (term.first == func)
{
return;
}
}
TermFuncs.Push(std::make_pair(func, name));
}
//==========================================================================
//
// call_terms
//
//==========================================================================
void call_terms()
{
for(int i = TermFuncs.Size()-1; i >= 0; i--)
{
TermFuncs[i].first();
}
TermFuncs.Clear();
}
//==========================================================================
//
// popterm
//
// Removes the most recently register atterm function.
//
//==========================================================================
void popterm()
{
if (TermFuncs.Size() > 0)
{
TermFuncs.Pop();
}
}

6
src/utility/atterm.h Normal file
View file

@ -0,0 +1,6 @@
#pragma once
void addterm (void (*func)(void), const char *name);
#define atterm(t) addterm (t, #t)
void popterm ();
void call_terms();

View file

@ -86,6 +86,30 @@
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/
#include "mconf.h"

View file

@ -70,6 +70,30 @@
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/

View file

@ -57,6 +57,30 @@
/*
Cephes Math Library Release 2.3: March, 1995
Copyright 1984, 1995 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/
#include "mconf.h"

View file

@ -42,6 +42,30 @@
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1985, 1995, 2000 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/
#include "mconf.h"

View file

@ -57,6 +57,31 @@
/*
Cephes Math Library Release 2.2: January, 1991
Copyright 1984, 1991 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/

View file

@ -57,6 +57,30 @@
/*
Cephes Math Library Release 2.3: March, 1995
Copyright 1984, 1995 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/

View file

@ -49,6 +49,30 @@
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/
#include "mconf.h"

View file

@ -44,6 +44,30 @@
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/
#include "mconf.h"

View file

@ -59,6 +59,30 @@
/*
Cephes Math Library Release 2.3: June, 1995
Copyright 1984, 1987, 1989, 1995 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/

View file

@ -51,6 +51,31 @@
/*
Cephes Math Library Release 2.0: April, 1987
Copyright 1984, 1987 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/

View file

@ -46,6 +46,31 @@
/*
Cephes Math Library Release 2.1: December, 1988
Copyright 1984, 1987, 1988 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/

View file

@ -49,6 +49,30 @@
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
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. Neither the name of the <ORGANIZATION> nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/

Some files were not shown because too many files have changed in this diff Show more