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 clone_depth: 10
image:
- Visual Studio 2019
- Visual Studio 2015
environment: environment:
matrix: matrix:
- GENERATOR: "Visual Studio 14 2015" - ARCH: x64
CONFIGURATION: Release - ARCH: Win32
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"
build_script: build_script:
- md build - md build
- cd build - cd build
- cmake -G "%GENERATOR%" -T "%TOOLSET%" -DPK3_QUIET_ZIPDIR=YES .. - cmake -A %ARCH% -DPK3_QUIET_ZIPDIR=YES ..
- cmake --build . --config "%CONFIGURATION%" -- -maxcpucount -verbosity:minimal - cmake --build . --config Release -- -maxcpucount -verbosity:minimal
after_build: 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" - 7z a ..\gzdoom.zip "%OUTPUT_DIR%gzdoom.exe" "%OUTPUT_DIR%*.pk3"
artifacts: artifacts:

1
.gitignore vendored
View file

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

View file

@ -239,7 +239,21 @@ else()
else() else()
set( ALL_C_FLAGS "-ffp-contract=off" ) set( ALL_C_FLAGS "-ffp-contract=off" )
endif() 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( REL_C_FLAGS "" )
set( DEB_C_FLAGS "" ) set( DEB_C_FLAGS "" )
@ -310,6 +324,19 @@ else()
set( ZLIB_LIBRARY z ) set( ZLIB_LIBRARY z )
endif() 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( ${HAVE_VM_JIT} )
if( ASMJIT_FOUND AND NOT FORCE_INTERNAL_ASMJIT ) if( ASMJIT_FOUND AND NOT FORCE_INTERNAL_ASMJIT )
message( STATUS "Using system asmjit, includes found at ${ASMJIT_INCLUDE_DIR}" ) 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/nodebuilder/nodebuild_utility.cpp
utility/sc_man.cpp utility/sc_man.cpp
utility/stats.cpp utility/stats.cpp
utility/atterm.cpp
utility/cmdlib.cpp utility/cmdlib.cpp
utility/colormatcher.cpp utility/colormatcher.cpp
utility/configfile.cpp utility/configfile.cpp
@ -1451,10 +1452,9 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
# Need to enable intrinsics for these files. # Need to enable intrinsics for these files.
if( SSE_MATTERS ) if( SSE_MATTERS )
set_source_files_properties( set_source_files_properties(
gl/system/gl_swframebuffer.cpp rendering/polyrenderer/poly_all.cpp
polyrenderer/poly_all.cpp rendering/swrenderer/r_all.cpp
swrenderer/r_all.cpp utility/x86.cpp
x86.cpp
PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" ) PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
endif() endif()
endif() endif()

View file

@ -74,7 +74,7 @@ extern bool insave;
CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH) CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH)
CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO) CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO)
CVAR (Bool, cl_blockcheats, false, 0) CVAR (Int, cl_blockcheats, 0, 0)
CCMD (toggleconsole) CCMD (toggleconsole)
{ {
@ -88,9 +88,9 @@ bool CheckCheatmode (bool printmsg)
if (printmsg) Printf ("sv_cheats must be true to enable this command.\n"); if (printmsg) Printf ("sv_cheats must be true to enable this command.\n");
return true; 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; return true;
} }
else else

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -767,6 +767,11 @@ bool MapLoader::LoadExtendedNodes (FileReader &dalump, uint32_t id)
static bool P_CheckV4Nodes(MapData *map) static bool P_CheckV4Nodes(MapData *map)
{ {
if (map->Size(ML_NODES) == 0)
{
return false;
}
char header[8]; char header[8];
map->Read(ML_NODES, 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()); 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 = GStrings.exists(label.GetChars() + 1)? label : FString(rsp->Reply);
reply->Reply = label;
} }
else else
{ {

View file

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

View file

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

View file

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

View file

@ -33,6 +33,7 @@
#include "i_common.h" #include "i_common.h"
#include "s_sound.h" #include "s_sound.h"
#include "atterm.h"
#include <sys/sysctl.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) void Mac_I_FatalError(const char* const message)
{ {

View file

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

View file

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

View file

@ -54,6 +54,7 @@
#include "v_text.h" #include "v_text.h"
#include "version.h" #include "version.h"
#include "doomerrors.h" #include "doomerrors.h"
#include "atterm.h"
#include "gl/system/gl_framebuffer.h" #include "gl/system/gl_framebuffer.h"
#include "vulkan/system/vk_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 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); void I_DebugPrint (const char *cp);
// Print a console string // Print a console string

View file

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

View file

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

View file

@ -56,6 +56,7 @@
#include "doomerrors.h" #include "doomerrors.h"
#include "i_system.h" #include "i_system.h"
#include "g_game.h" #include "g_game.h"
#include "atterm.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -89,47 +90,9 @@ FArgs *Args;
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
static void (*TermFuncs[MAX_TERMS]) ();
static const char *TermNames[MAX_TERMS];
static int NumTerms;
// CODE -------------------------------------------------------------------- // 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 () static void NewFailure ()
{ {

View file

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

View file

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

View file

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

View file

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

View file

@ -35,13 +35,61 @@
EXTERN_CVAR(Float, transsouls) 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) 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) DEFINE_ACTION_FUNCTION(DShape2D, Clear)
{ {
PARAM_SELF_PROLOGUE(DShape2D); PARAM_SELF_PROLOGUE(DShape2D);
PARAM_INT(which); 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_Coords ) self->mCoords.Clear();
if ( which&C_Indices ) self->mIndices.Clear(); if ( which&C_Indices ) self->mIndices.Clear();
return 0; return 0;
@ -53,6 +101,7 @@ DEFINE_ACTION_FUNCTION(DShape2D, PushVertex)
PARAM_FLOAT(x); PARAM_FLOAT(x);
PARAM_FLOAT(y); PARAM_FLOAT(y);
self->mVertices.Push(DVector2(x,y)); self->mVertices.Push(DVector2(x,y));
self->dirty = true;
return 0; return 0;
} }
@ -380,13 +429,22 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
if (!img->isHardwareCanvas() && parms.remap != nullptr && !parms.remap->Inactive) if (!img->isHardwareCanvas() && parms.remap != nullptr && !parms.remap->Inactive)
dg.mTranslation = parms.remap; 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; double minx = 16383, miny = 16383, maxx = -16384, maxy = -16384;
for ( int i=0; i<dg.mVertCount; i++ ) for ( int i=0; i<dg.mVertCount; i++ )
{ {
if ( shape->mVertices[i].X < minx ) minx = shape->mVertices[i].X; if ( shape->mTransformedVertices[i].X < minx ) minx = shape->mTransformedVertices[i].X;
if ( shape->mVertices[i].Y < miny ) miny = shape->mVertices[i].Y; if ( shape->mTransformedVertices[i].Y < miny ) miny = shape->mTransformedVertices[i].Y;
if ( shape->mVertices[i].X > maxx ) maxx = shape->mVertices[i].X; if ( shape->mTransformedVertices[i].X > maxx ) maxx = shape->mTransformedVertices[i].X;
if ( shape->mVertices[i].Y > maxy ) maxy = shape->mVertices[i].Y; 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) 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); dg.mVertIndex = (int)mVertices.Reserve(dg.mVertCount);
TwoDVertex *ptr = &mVertices[dg.mVertIndex]; TwoDVertex *ptr = &mVertices[dg.mVertIndex];
for ( int i=0; i<dg.mVertCount; i++ ) 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.mIndexIndex = mIndices.Size();
dg.mIndexCount += shape->mIndices.Size(); dg.mIndexCount += shape->mIndices.Size();
for ( int i=0; i<int(shape->mIndices.Size()); i+=3 ) 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); mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0);
} }
poly.mIndexIndex = mIndices.Size(); poly.mIndexIndex = mIndices.Size();
poly.mIndexCount += (npoints - 2) * 3;
if (indices == nullptr || indexcount == 0) if (indices == nullptr || indexcount == 0)
{ {
poly.mIndexCount += (npoints - 2) * 3;
for (int i = 2; i < npoints; ++i) for (int i = 2; i < npoints; ++i)
{ {
AddIndices(poly.mVertIndex, 3, 0, i - 1, i); AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
@ -496,10 +554,11 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
} }
else else
{ {
poly.mIndexCount += (int)indexcount;
int addr = mIndices.Reserve(indexcount); int addr = mIndices.Reserve(indexcount);
for (size_t i = 0; i < indexcount; i++) 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; struct DrawParms;
class DShape2DTransform : public DObject
{
DECLARE_CLASS(DShape2DTransform, DObject)
public:
DShape2DTransform()
{
transform.Identity();
}
DMatrix3x3 transform;
};
// intermediate struct for shape drawing // intermediate struct for shape drawing
enum EClearWhich enum EClearWhich
@ -23,9 +35,21 @@ class DShape2D : public DObject
DECLARE_CLASS(DShape2D,DObject) DECLARE_CLASS(DShape2D,DObject)
public: public:
DShape2D()
{
transform.Identity();
}
TArray<int> mIndices; TArray<int> mIndices;
TArray<DVector2> mVertices; TArray<DVector2> mVertices;
TArray<DVector2> mCoords; 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 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->Scale = { screen->mScreenViewport.width / (float)mBuffers->GetWidth(), screen->mScreenViewport.height / (float)mBuffers->GetHeight() };
mPresentShader->Uniforms->Offset = { 0.0f, 0.0f }; mPresentShader->Uniforms->Offset = { 0.0f, 0.0f };
mPresentShader->Uniforms.Set(); mPresentShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresentShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad(); RenderScreenQuad();
} }

View file

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

View file

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

View file

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

View file

@ -189,9 +189,21 @@ bool FGLRenderState::ApplyShader()
matrixToGL(identityMatrix, activeShader->normalmodelmatrix_index); matrixToGL(identityMatrix, activeShader->normalmodelmatrix_index);
} }
auto index = screen->mLights->BindUBO(mLightIndex); int index = mLightIndex;
activeShader->muLightIndex.Set(index); // 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; return true;
} }

View file

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

View file

@ -57,6 +57,7 @@
#include "hwrenderer/scene/hw_portal.h" #include "hwrenderer/scene/hw_portal.h"
#include "hwrenderer/utility/hw_vrmodes.h" #include "hwrenderer/utility/hw_vrmodes.h"
#include "gl/renderer/gl_renderer.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/renderer/gl_postprocessstate.h"
#include "gl/system/gl_framebuffer.h" #include "gl/system/gl_framebuffer.h"
#include "gl/shaders/gl_shaderprogram.h" #include "gl/shaders/gl_shaderprogram.h"
#include "gl/system/gl_buffers.h"
#include "menu/menu.h" #include "menu/menu.h"
EXTERN_CVAR(Int, vr_mode) EXTERN_CVAR(Int, vr_mode)
@ -174,7 +175,8 @@ void FGLRenderer::prepareInterleavedPresent(FPresentShaderBase& shader)
screen->mScreenViewport.height / (float)mBuffers->GetHeight() screen->mScreenViewport.height / (float)mBuffers->GetHeight()
}; };
shader.Uniforms->Offset = { 0.0f, 0.0f }; 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; int windowHOffset = 0;
mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset; mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset;
mPresent3dColumnShader->Uniforms.Set(); mPresent3dColumnShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dColumnShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad(); RenderScreenQuad();
} }
@ -225,7 +228,8 @@ void FGLRenderer::PresentRowInterleaved()
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom + screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2; ) % 2;
mPresent3dRowShader->Uniforms.Set(); mPresent3dRowShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dRowShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad(); RenderScreenQuad();
} }
@ -256,7 +260,8 @@ void FGLRenderer::PresentCheckerInterleaved()
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom + 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 ) % 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(); 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() void GLDataBuffer::BindBase()

View file

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

View file

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

View file

@ -177,7 +177,7 @@ void gl_LoadExtensions()
// Mesa implements shader storage only for fragment shaders. // 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. // 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); glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &v);
if (v == 0) if (v == 0)
gl.flags &= ~RFL_SHADER_STORAGE_BUFFER; gl.flags &= ~RFL_SHADER_STORAGE_BUFFER;

View file

@ -3,6 +3,8 @@
#include <stddef.h> #include <stddef.h>
#include <assert.h> #include <assert.h>
class FRenderState;
// The low level code needs to know which attributes exist. // The low level code needs to know which attributes exist.
// OpenGL needs to change the state of all of them per buffer binding. // 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. // 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. // Can be either uniform or shader storage buffer, depending on its needs.
public: public:
virtual void BindRange(size_t start, size_t length) = 0; virtual void BindRange(FRenderState *state, size_t start, size_t length) = 0;
virtual void BindBase() = 0;
}; };

View file

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

View file

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

View file

@ -126,14 +126,16 @@ public:
mBuffer = screen->CreateDataBuffer(bindingpoint, false, false); mBuffer = screen->CreateDataBuffer(bindingpoint, false, false);
} }
void Set(bool bind = true) void SetData()
{ {
if (mBuffer != nullptr) if (mBuffer != nullptr)
mBuffer->SetData(sizeof(T), &Values); mBuffer->SetData(sizeof(T), &Values);
}
// Let's hope this can be done better when things have moved further ahead. IDataBuffer* GetBuffer() const
// This really is not the best place to add something that depends on API behavior. {
if (bind) mBuffer->BindBase(); // OpenGL needs to mess around with this in ways that should not be part of the interface.
return mBuffer;
} }
T *operator->() { return &Values; } 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. // 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. // 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. // 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; mBufferType = true;
mBlockAlign = 0; mBlockAlign = 0;
@ -74,7 +74,6 @@ FLightBuffer::~FLightBuffer()
void FLightBuffer::Clear() void FLightBuffer::Clear()
{ {
mIndex = 0; mIndex = 0;
mLastMappedIndex = UINT_MAX;
} }
int FLightBuffer::UploadLights(FDynLightData &data) 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. // 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; unsigned int offset = (index / mBlockAlign) * mBlockAlign;
if (offset != mLastMappedIndex) *pOffset = offset * ELEMENT_SIZE;
{ *pSize = mBlockSize * ELEMENT_SIZE;
mLastMappedIndex = offset;
mBuffer->BindRange(offset * ELEMENT_SIZE, mBlockSize * ELEMENT_SIZE);
}
return (index - offset); return (index - offset);
} }

View file

@ -15,7 +15,6 @@ class FLightBuffer
bool mBufferType; bool mBufferType;
std::atomic<unsigned int> mIndex; std::atomic<unsigned int> mIndex;
unsigned int mLastMappedIndex;
unsigned int mBlockAlign; unsigned int mBlockAlign;
unsigned int mBlockSize; unsigned int mBlockSize;
unsigned int mBufferSize; unsigned int mBufferSize;
@ -34,32 +33,12 @@ public:
void Unmap() { mBuffer->Unmap(); } void Unmap() { mBuffer->Unmap(); }
unsigned int GetBlockSize() const { return mBlockSize; } unsigned int GetBlockSize() const { return mBlockSize; }
bool GetBufferType() const { return mBufferType; } bool GetBufferType() const { return mBufferType; }
int GetBinding(unsigned int index, size_t* pOffset, size_t* pSize);
int DoBindUBO(unsigned int index); // OpenGL needs the buffer to mess around with the binding.
IDataBuffer* GetBuffer() const
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)
{ {
if (!mBufferType && index > -1) return mBuffer;
{
index = DoBindUBO(index);
}
return index;
}
// The parameter is a reminder for Vulkan.
void BindBase()
{
mBuffer->BindBase();
mLastMappedIndex = UINT_MAX;
} }
}; };

View file

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

View file

@ -65,6 +65,8 @@ protected:
IShadowMap &operator=(IShadowMap &) = delete; IShadowMap &operator=(IShadowMap &) = delete;
// OpenGL storage buffer with the list of lights in the shadow map texture // 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; IDataBuffer *mLightList = nullptr;
// OpenGL storage buffers for the AABB tree // OpenGL storage buffers for the AABB tree

View file

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

View file

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

View file

@ -35,7 +35,7 @@ void VkPostprocess::SetActiveRenderTarget()
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false); imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
imageTransition.execute(fb->GetDrawCommands()); 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) 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) VkPPShader::VkPPShader(PPShader *shader)
@ -585,6 +597,7 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
VkTextureImage *tex = GetTexture(output.Type, output.Texture); VkTextureImage *tex = GetTexture(output.Type, output.Texture);
VkImageView view; VkImageView view;
std::unique_ptr<VulkanFramebuffer> *framebufferptr = nullptr;
int w, h; int w, h;
if (tex) if (tex)
{ {
@ -597,15 +610,17 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
view = tex->View->view; view = tex->View->view;
w = tex->Image->width; w = tex->Image->width;
h = tex->Image->height; h = tex->Image->height;
framebufferptr = &tex->PPFramebuffer;
} }
else else
{ {
view = fb->swapChain->swapChainImageViews[fb->presentImageIndex]; view = fb->swapChain->swapChainImageViews[fb->presentImageIndex];
framebufferptr = &fb->swapChain->framebuffers[fb->presentImageIndex];
w = fb->swapChain->actualExtent.width; w = fb->swapChain->actualExtent.width;
h = fb->swapChain->actualExtent.height; h = fb->swapChain->actualExtent.height;
} }
auto &framebuffer = passSetup->Framebuffers[view]; auto &framebuffer = *framebufferptr;
if (!framebuffer) if (!framebuffer)
{ {
FramebufferBuilder builder; FramebufferBuilder builder;

View file

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

View file

@ -59,7 +59,6 @@ public:
VkRenderPassKey PassKey; VkRenderPassKey PassKey;
std::unique_ptr<VulkanRenderPass> RenderPasses[8]; std::unique_ptr<VulkanRenderPass> RenderPasses[8];
std::map<VkPipelineKey, std::unique_ptr<VulkanPipeline>> Pipelines; std::map<VkPipelineKey, std::unique_ptr<VulkanPipeline>> Pipelines;
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffer;
private: private:
std::unique_ptr<VulkanRenderPass> CreateRenderPass(int clearTargets); 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(); EndRenderPass();
mRenderTarget.View = view; mRenderTarget.Image = image;
mRenderTarget.DepthStencil = depthStencilView; mRenderTarget.DepthStencil = depthStencilView;
mRenderTarget.Width = width; mRenderTarget.Width = width;
mRenderTarget.Height = height; mRenderTarget.Height = height;
@ -552,14 +552,14 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer)
mPassSetup = fb->GetRenderPassManager()->GetRenderPass(key); mPassSetup = fb->GetRenderPassManager()->GetRenderPass(key);
auto &framebuffer = mPassSetup->Framebuffer[mRenderTarget.View->view]; auto &framebuffer = mRenderTarget.Image->RSFramebuffers[key];
if (!framebuffer) if (!framebuffer)
{ {
auto buffers = fb->GetBuffers(); auto buffers = fb->GetBuffers();
FramebufferBuilder builder; FramebufferBuilder builder;
builder.setRenderPass(mPassSetup->GetRenderPass(0)); builder.setRenderPass(mPassSetup->GetRenderPass(0));
builder.setSize(mRenderTarget.Width, mRenderTarget.Height); builder.setSize(mRenderTarget.Width, mRenderTarget.Height);
builder.addAttachment(mRenderTarget.View); builder.addAttachment(mRenderTarget.Image->View.get());
if (key.DrawBuffers > 1) if (key.DrawBuffers > 1)
builder.addAttachment(buffers->SceneFog.View.get()); builder.addAttachment(buffers->SceneFog.View.get());
if (key.DrawBuffers > 2) if (key.DrawBuffers > 2)

View file

@ -12,6 +12,7 @@
#include "hwrenderer/textures/hw_material.h" #include "hwrenderer/textures/hw_material.h"
class VkRenderPassSetup; class VkRenderPassSetup;
class VkTextureImage;
class VkRenderState : public FRenderState class VkRenderState : public FRenderState
{ {
@ -43,7 +44,7 @@ public:
void EnableDrawBuffers(int count) override; void EnableDrawBuffers(int count) override;
void BeginFrame(); 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 Bind(int bindingpoint, uint32_t offset);
void EndRenderPass(); void EndRenderPass();
void EndFrame(); void EndFrame();
@ -112,7 +113,7 @@ protected:
struct RenderTarget struct RenderTarget
{ {
VulkanImageView *View = nullptr; VkTextureImage *Image = nullptr;
VulkanImageView *DepthStencil = nullptr; VulkanImageView *DepthStencil = nullptr;
int Width = 0; int Width = 0;
int Height = 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 BindRange(FRenderState *state, size_t start, size_t length) override;
void BindBase() override;
int bindingpoint; int bindingpoint;
}; };

View file

@ -128,7 +128,14 @@ void VulkanFrameBuffer::InitializeState()
first = false; 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; hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
glslversion = 4.50f; glslversion = 4.50f;
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment; uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment;
@ -145,7 +152,7 @@ void VulkanFrameBuffer::InitializeState()
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight()); mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
mSkyData = new FSkyVertexBuffer; mSkyData = new FSkyVertexBuffer;
mViewpoints = new GLViewpointBuffer; mViewpoints = new HWViewpointBuffer;
mLights = new FLightBuffer(); mLights = new FLightBuffer();
CreateFanToTrisIndexBuffer(); CreateFanToTrisIndexBuffer();
@ -199,6 +206,7 @@ void VulkanFrameBuffer::DeleteFrameObjects()
{ {
FrameDeleteList.Images.clear(); FrameDeleteList.Images.clear();
FrameDeleteList.ImageViews.clear(); FrameDeleteList.ImageViews.clear();
FrameDeleteList.Framebuffers.clear();
FrameDeleteList.Buffers.clear(); FrameDeleteList.Buffers.clear();
FrameDeleteList.Descriptors.clear(); FrameDeleteList.Descriptors.clear();
FrameDeleteList.DescriptorPools.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 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); bool useSSAO = (gl_ssao != 0);
GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount()); 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.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier0.execute(GetDrawCommands()); 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; IntRect bounds;
bounds.left = bounds.top = 0; 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.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
barrier1.execute(GetDrawCommands()); 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); tex->SetUpdated(true);
} }
@ -709,11 +717,12 @@ void VulkanFrameBuffer::UpdatePalette()
FTexture *VulkanFrameBuffer::WipeStartScreen() FTexture *VulkanFrameBuffer::WipeStartScreen()
{ {
const auto &viewport = screen->mScreenViewport; SetViewportRects(nullptr);
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()); auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeStartScreen"); systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeStartScreen");
return tex; return tex;
} }
@ -724,11 +733,10 @@ FTexture *VulkanFrameBuffer::WipeEndScreen()
Draw2D(); Draw2D();
Clear2D(); Clear2D();
const auto &viewport = screen->mScreenViewport; auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1);
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture()); auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeEndScreen"); systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeEndScreen");
return tex; return tex;
} }

View file

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

View file

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

View file

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

View file

@ -72,8 +72,10 @@ void VkHardwareTexture::Reset()
auto &deleteList = fb->FrameDeleteList; auto &deleteList = fb->FrameDeleteList;
if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image)); if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image));
if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View)); 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.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image));
if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View)); 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(); mImage.reset();
mDepthStencil.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 = viewbuilder.create(fb->device);
mImage.View->SetDebugName(name); 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_objects.h"
#include "vulkan/system/vk_builders.h" #include "vulkan/system/vk_builders.h"
#include "vulkan/renderer/vk_renderpass.h"
class VkTextureImage class VkTextureImage
{ {
@ -23,6 +24,8 @@ public:
std::unique_ptr<VulkanImageView> DepthOnlyView; std::unique_ptr<VulkanImageView> DepthOnlyView;
VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
std::unique_ptr<VulkanFramebuffer> PPFramebuffer;
std::map<VkRenderPassKey, std::unique_ptr<VulkanFramebuffer>> RSFramebuffers;
}; };
class VkImageTransition class VkImageTransition

View file

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

View file

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

View file

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

View file

@ -82,6 +82,8 @@ static const FLOP FxFlops[] =
{ NAME_CosH, FLOP_COSH, [](double v) { return g_cosh(v); } }, { NAME_CosH, FLOP_COSH, [](double v) { return g_cosh(v); } },
{ NAME_SinH, FLOP_SINH, [](double v) { return g_sinh(v); } }, { NAME_SinH, FLOP_SINH, [](double v) { return g_sinh(v); } },
{ NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(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 this is a local variable we need another register for the result.
if (trueop.Fixed) 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); build->Emit(truex->ValueType->GetMoveOp(), out.RegNum, trueop.RegNum, 0);
} }
else out = trueop; else out = trueop;
@ -6127,18 +6129,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
{ {
if (sym->mVersion <= ctx.Version) if (sym->mVersion <= ctx.Version)
{ {
if (!(ctx.Function->Variants[0].Flags & VARF_Deprecated) && Wads.GetLumpFile(ctx.Lump) == 0) // 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.
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); // 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.
else const bool internal = (ctx.Function->Variants[0].Flags & VARF_Deprecated) && Wads.GetLumpFile(ctx.Lump) == 0;
{
// Allow use of deprecated symbols in deprecated functions of the internal code. This is meant to allow deprecated code to remain as it was, ScriptPosition.Message(internal ? MSG_DEBUGMSG : MSG_WARNING,
// even if it depends on some deprecated symbol. "%sAccessing deprecated global variable %s - deprecated since %d.%d.%d", internal ? TEXTCOLOR_BLUE : "",
// The main motivation here is to keep the deprecated static functions accessing the global level variable as they were. sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision);
// 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);
}
} }
} }
@ -7425,7 +7424,6 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
{ {
bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta; bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta;
arrayvar.Free(build);
start = ExpEmit(build, REGT_POINTER); start = ExpEmit(build, REGT_POINTER);
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0)); build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
@ -7445,18 +7443,18 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
arraymemberbase->membervar = origmembervar; arraymemberbase->membervar = origmembervar;
arraymemberbase->AddressRequested = origaddrreq; arraymemberbase->AddressRequested = origaddrreq;
Array->ValueType = origvaluetype; Array->ValueType = origvaluetype;
arrayvar.Free(build);
} }
else if (Array->ExprType == EFX_ArrayElement && Array->isStaticArray()) 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); arrayvar.Free(build);
start = ExpEmit(build, REGT_POINTER); start = ExpEmit(build, REGT_POINTER);
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0)); 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; nestedarray = true;
} }
else start = arrayvar; else start = arrayvar;
@ -7514,7 +7512,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
else else
{ {
ExpEmit indexv(index->Emit(build)); ExpEmit indexv(index->Emit(build));
if (SizeAddr != ~0u) if (SizeAddr != ~0u || nestedarray)
{ {
build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum); build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum);
bound.Free(build); bound.Free(build);
@ -11352,8 +11350,59 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
{ {
if (RegNum == -1) if (RegNum == -1)
{ {
if (!(VarFlags & VARF_Out)) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); if (!(VarFlags & VARF_Out))
else RegNum = build->Registers[REGT_POINTER].Get(1); {
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 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) int ObjArrayPush(FDynArray_Obj *self, DObject *obj)
{ {
if (self == nullptr) NullParam("\"self\"");
GC::WriteBarrier(obj); GC::WriteBarrier(obj);
return self->Push(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) void ObjArrayInsert(FDynArray_Obj *self,int index, DObject *obj)
{ {
if (self == nullptr) NullParam("\"self\"");
GC::WriteBarrier(obj); GC::WriteBarrier(obj);
self->Insert(index, obj); self->Insert(index, obj);
} }

View file

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

View file

@ -37,8 +37,16 @@ public:
void Return(int reg, int count); void Return(int reg, int count);
bool Reuse(int regnum); 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: private:
VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used) VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used)
VM_UWORD Dirty[256/32];
int MostUsed; int MostUsed;
friend class VMFunctionBuilder; friend class VMFunctionBuilder;

View file

@ -181,6 +181,8 @@ static const char *const FlopNames[] =
"cosh", "cosh",
"sinh", "sinh",
"tanh", "tanh",
"round",
}; };
static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const VMScriptFunction *func); 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.Namespace = ns;
bag.Version = { 2, 0, 0 }; bag.Version = { 2, 0, 0 };
bag.fromDecorate = true; bag.fromDecorate = true;
bag.ScriptPosition = sc;
info = ParseActorHeader(sc, &bag); info = ParseActorHeader(sc, &bag);
sc.MustGetToken('{'); sc.MustGetToken('{');
while (sc.MustGetAnyToken(), sc.TokenType != '}') 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"); 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(); asmjit::CBNode *cursorBefore = cc.getCursor();
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature()); auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature());
call->setInlineComment(target->PrintableName.GetChars()); call->setInlineComment(target->PrintableName.GetChars());

View file

@ -985,6 +985,7 @@ void JitCompiler::EmitFLOP()
case FLOP_COSH: func = g_cosh; break; case FLOP_COSH: func = g_cosh; break;
case FLOP_SINH: func = g_sinh; break; case FLOP_SINH: func = g_sinh; break;
case FLOP_TANH: func = g_tanh; break; case FLOP_TANH: func = g_tanh; break;
case FLOP_ROUND: func = round; break;
} }
auto result = newResultXmmSd(); 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_COSH: return g_cosh(v);
case FLOP_SINH: return g_sinh(v); case FLOP_SINH: return g_sinh(v);
case FLOP_TANH: return g_tanh(v); case FLOP_TANH: return g_tanh(v);
case FLOP_ROUND: return round(v);
} }
assert(0); assert(0);
return 0; return 0;

View file

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

View file

@ -1353,7 +1353,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *
// This is a global variable. // This is a global variable.
if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; 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); 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; f->mVersion = field->Version;
} }

View file

@ -933,7 +933,8 @@ void pre_resample(Sample * sp)
return; 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[newlen >> FRACTION_BITS] = 0;
*dest++ = src[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 Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier 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" #include "mconf.h"

View file

@ -70,6 +70,30 @@
/* /*
Cephes Math Library Release 2.8: June, 2000 Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier 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 Cephes Math Library Release 2.3: March, 1995
Copyright 1984, 1995 by Stephen L. Moshier 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" #include "mconf.h"

View file

@ -42,6 +42,30 @@
/* /*
Cephes Math Library Release 2.8: June, 2000 Cephes Math Library Release 2.8: June, 2000
Copyright 1985, 1995, 2000 by Stephen L. Moshier 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" #include "mconf.h"

View file

@ -57,6 +57,31 @@
/* /*
Cephes Math Library Release 2.2: January, 1991 Cephes Math Library Release 2.2: January, 1991
Copyright 1984, 1991 by Stephen L. Moshier 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 Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/ */

View file

@ -57,6 +57,30 @@
/* /*
Cephes Math Library Release 2.3: March, 1995 Cephes Math Library Release 2.3: March, 1995
Copyright 1984, 1995 by Stephen L. Moshier 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 Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier 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" #include "mconf.h"

View file

@ -44,6 +44,30 @@
/* /*
Cephes Math Library Release 2.8: June, 2000 Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier 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" #include "mconf.h"

View file

@ -59,6 +59,30 @@
/* /*
Cephes Math Library Release 2.3: June, 1995 Cephes Math Library Release 2.3: June, 1995
Copyright 1984, 1987, 1989, 1995 by Stephen L. Moshier 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 Cephes Math Library Release 2.0: April, 1987
Copyright 1984, 1987 by Stephen L. Moshier 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 Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/ */

View file

@ -46,6 +46,31 @@
/* /*
Cephes Math Library Release 2.1: December, 1988 Cephes Math Library Release 2.1: December, 1988
Copyright 1984, 1987, 1988 by Stephen L. Moshier 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 Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/ */

View file

@ -49,6 +49,30 @@
/* /*
Cephes Math Library Release 2.8: June, 2000 Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier 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