mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 00:41:55 +00:00
- Backend update from GZDoom
* music system improvements * Zip64 support * fixes for menu scaling on ultrawide screens * Mac default paths fixed * lightmap code (not active yet)
This commit is contained in:
parent
380864d6fb
commit
21b4862460
48 changed files with 906 additions and 144 deletions
|
@ -1101,6 +1101,7 @@ set (PCH_SOURCES
|
|||
common/2d/v_2ddrawer.cpp
|
||||
common/2d/v_drawtext.cpp
|
||||
common/2d/v_draw.cpp
|
||||
common/2d/wipe.cpp
|
||||
common/thirdparty/gain_analysis.cpp
|
||||
common/thirdparty/sfmt/SFMT.cpp
|
||||
common/fonts/singlelumpfont.cpp
|
||||
|
|
444
source/common/2d/wipe.cpp
Executable file
444
source/common/2d/wipe.cpp
Executable file
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
** wipe.cpp
|
||||
** Screen wipe implementation
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2016 Randy Heit
|
||||
** Copyright 2005-2022 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 "v_video.h"
|
||||
#include "m_random.h"
|
||||
#include "wipe.h"
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "hw_material.h"
|
||||
#include "v_draw.h"
|
||||
#include "s_soundinternal.h"
|
||||
#include "i_time.h"
|
||||
|
||||
class FBurnTexture : public FTexture
|
||||
{
|
||||
TArray<uint32_t> WorkBuffer;
|
||||
public:
|
||||
FBurnTexture(int w, int h)
|
||||
: WorkBuffer(w*h, true)
|
||||
{
|
||||
Width = w;
|
||||
Height = h;
|
||||
}
|
||||
|
||||
FBitmap GetBgraBitmap(const PalEntry*, int *trans) override
|
||||
{
|
||||
FBitmap bmp;
|
||||
bmp.Create(Width, Height);
|
||||
bmp.CopyPixelDataRGB(0, 0, (uint8_t*)WorkBuffer.Data(), Width, Height, 4, Width*4, 0, CF_RGBA, nullptr);
|
||||
if (trans) *trans = 0;
|
||||
return bmp;
|
||||
}
|
||||
|
||||
uint32_t *GetBuffer()
|
||||
{
|
||||
return WorkBuffer.Data();
|
||||
}
|
||||
};
|
||||
|
||||
int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density)
|
||||
{
|
||||
// This is a modified version of the fire that was once used
|
||||
// on the player setup menu.
|
||||
static int voop;
|
||||
|
||||
int a, b;
|
||||
uint8_t *from;
|
||||
|
||||
// generator
|
||||
from = &burnarray[width * height];
|
||||
b = voop;
|
||||
voop += density / 3;
|
||||
for (a = 0; a < density/8; a++)
|
||||
{
|
||||
unsigned int offs = (a+b) & (width - 1);
|
||||
unsigned int v = M_Random();
|
||||
v = min(from[offs] + 4 + (v & 15) + (v >> 3) + (M_Random() & 31), 255u);
|
||||
from[offs] = from[width*2 + ((offs + width*3/2) & (width - 1))] = v;
|
||||
}
|
||||
|
||||
density = min(density + 10, width * 7);
|
||||
|
||||
from = burnarray;
|
||||
for (b = 0; b <= height; b += 2)
|
||||
{
|
||||
uint8_t *pixel = from;
|
||||
|
||||
// special case: first pixel on line
|
||||
uint8_t *p = pixel + (width << 1);
|
||||
unsigned int top = *p + *(p + width - 1) + *(p + 1);
|
||||
unsigned int bottom = *(pixel + (width << 2));
|
||||
unsigned int c1 = (top + bottom) >> 2;
|
||||
if (c1 > 1) c1--;
|
||||
*pixel = c1;
|
||||
*(pixel + width) = (c1 + bottom) >> 1;
|
||||
pixel++;
|
||||
|
||||
// main line loop
|
||||
for (a = 1; a < width-1; a++)
|
||||
{
|
||||
// sum top pixels
|
||||
p = pixel + (width << 1);
|
||||
top = *p + *(p - 1) + *(p + 1);
|
||||
|
||||
// bottom pixel
|
||||
bottom = *(pixel + (width << 2));
|
||||
|
||||
// combine pixels
|
||||
c1 = (top + bottom) >> 2;
|
||||
if (c1 > 1) c1--;
|
||||
|
||||
// store pixels
|
||||
*pixel = c1;
|
||||
*(pixel + width) = (c1 + bottom) >> 1; // interpolate
|
||||
|
||||
// next pixel
|
||||
pixel++;
|
||||
}
|
||||
|
||||
// special case: last pixel on line
|
||||
p = pixel + (width << 1);
|
||||
top = *p + *(p - 1) + *(p - width + 1);
|
||||
bottom = *(pixel + (width << 2));
|
||||
c1 = (top + bottom) >> 2;
|
||||
if (c1 > 1) c1--;
|
||||
*pixel = c1;
|
||||
*(pixel + width) = (c1 + bottom) >> 1;
|
||||
|
||||
// next line
|
||||
from += width << 1;
|
||||
}
|
||||
|
||||
// Check for done-ness. (Every pixel with level 126 or higher counts as done.)
|
||||
for (a = width * height, from = burnarray; a != 0; --a, ++from)
|
||||
{
|
||||
if (*from < 126)
|
||||
{
|
||||
return density;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
class Wiper_Crossfade : public Wiper
|
||||
{
|
||||
public:
|
||||
bool Run(int ticks) override;
|
||||
|
||||
private:
|
||||
int Clock = 0;
|
||||
};
|
||||
|
||||
class Wiper_Melt : public Wiper
|
||||
{
|
||||
public:
|
||||
Wiper_Melt();
|
||||
bool Run(int ticks) override;
|
||||
|
||||
private:
|
||||
enum { WIDTH = 320, HEIGHT = 200 };
|
||||
int y[WIDTH];
|
||||
};
|
||||
|
||||
class Wiper_Burn : public Wiper
|
||||
{
|
||||
public:
|
||||
~Wiper_Burn();
|
||||
bool Run(int ticks) override;
|
||||
void SetTextures(FGameTexture *startscreen, FGameTexture *endscreen) override;
|
||||
|
||||
private:
|
||||
static const int WIDTH = 64, HEIGHT = 64;
|
||||
uint8_t BurnArray[WIDTH * (HEIGHT + 5)] = {0};
|
||||
FBurnTexture *BurnTexture = nullptr;
|
||||
int Density = 4;
|
||||
int BurnTime = 8;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Screen wipes
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
Wiper *Wiper::Create(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case wipe_Burn:
|
||||
return new Wiper_Burn;
|
||||
|
||||
case wipe_Fade:
|
||||
return new Wiper_Crossfade;
|
||||
|
||||
case wipe_Melt:
|
||||
return new Wiper_Melt;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: WipeCleanup
|
||||
//
|
||||
// Release any resources that were specifically created for the wipe.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
Wiper::~Wiper()
|
||||
{
|
||||
if (startScreen != nullptr) delete startScreen;
|
||||
if (endScreen != nullptr) delete endScreen;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// WIPE: CROSSFADE ---------------------------------------------------------
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Crossfade :: Run
|
||||
//
|
||||
// Fades the old screen into the new one over 32 ticks.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool Wiper_Crossfade::Run(int ticks)
|
||||
{
|
||||
Clock += ticks;
|
||||
DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
|
||||
DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE);
|
||||
return Clock >= 32;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Melt Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
Wiper_Melt::Wiper_Melt()
|
||||
{
|
||||
y[0] = -(M_Random() & 15);
|
||||
for (int i = 1; i < WIDTH; ++i)
|
||||
{
|
||||
y[i] = clamp(y[i-1] + (M_Random() % 3) - 1, -15, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Melt :: Run
|
||||
//
|
||||
// Melts the old screen into the new one over 32 ticks.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool Wiper_Melt::Run(int ticks)
|
||||
{
|
||||
bool done;
|
||||
DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
|
||||
|
||||
// Copy the old screen in vertical strips on top of the new one.
|
||||
while (ticks--)
|
||||
{
|
||||
done = true;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
if (y[i] < HEIGHT)
|
||||
{
|
||||
if (y[i] < 0)
|
||||
y[i]++;
|
||||
else if (y[i] < 16)
|
||||
y[i] += y[i] + 1;
|
||||
else
|
||||
y[i] = min<int>(y[i] + 8, HEIGHT);
|
||||
done = false;
|
||||
}
|
||||
if (ticks == 0)
|
||||
{
|
||||
struct {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
} dpt;
|
||||
struct {
|
||||
int32_t left;
|
||||
int32_t top;
|
||||
int32_t right;
|
||||
int32_t bottom;
|
||||
} rect;
|
||||
|
||||
// Only draw for the final tick.
|
||||
|
||||
int w = startScreen->GetTexelWidth();
|
||||
int h = startScreen->GetTexelHeight();
|
||||
dpt.x = i * w / WIDTH;
|
||||
dpt.y = max(0, y[i] * h / HEIGHT);
|
||||
rect.left = dpt.x;
|
||||
rect.top = 0;
|
||||
rect.right = (i + 1) * w / WIDTH;
|
||||
rect.bottom = h - dpt.y;
|
||||
if (rect.bottom > rect.top)
|
||||
{
|
||||
DrawTexture(twod, startScreen, 0, dpt.y, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_ClipLeft, rect.left, DTA_ClipRight, rect.right, DTA_Masked, false, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Burn Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void Wiper_Burn::SetTextures(FGameTexture *startscreen, FGameTexture *endscreen)
|
||||
{
|
||||
startScreen = startscreen;
|
||||
endScreen = endscreen;
|
||||
BurnTexture = new FBurnTexture(WIDTH, HEIGHT);
|
||||
auto mat = FMaterial::ValidateTexture(endScreen, false);
|
||||
mat->ClearLayers();
|
||||
mat->AddTextureLayer(BurnTexture, false);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Burn Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
Wiper_Burn::~Wiper_Burn()
|
||||
{
|
||||
if (BurnTexture != nullptr) delete BurnTexture;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Burn :: Run
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool Wiper_Burn::Run(int ticks)
|
||||
{
|
||||
bool done;
|
||||
|
||||
|
||||
BurnTime += ticks;
|
||||
ticks *= 2;
|
||||
|
||||
// Make the fire burn
|
||||
done = false;
|
||||
while (!done && ticks--)
|
||||
{
|
||||
Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density);
|
||||
done = (Density < 0);
|
||||
}
|
||||
|
||||
BurnTexture->CleanHardwareTextures();
|
||||
endScreen->CleanHardwareData(false); // this only cleans the descriptor sets for the Vulkan backend. We do not want to delete the wipe screen's hardware texture here.
|
||||
|
||||
const uint8_t *src = BurnArray;
|
||||
uint32_t *dest = (uint32_t *)BurnTexture->GetBuffer();
|
||||
for (int y = HEIGHT; y != 0; --y)
|
||||
{
|
||||
for (int x = WIDTH; x != 0; --x)
|
||||
{
|
||||
uint8_t s = clamp<int>((*src++)*2, 0, 255);
|
||||
*dest++ = MAKEARGB(s,255,255,255);
|
||||
}
|
||||
}
|
||||
|
||||
DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
|
||||
DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Burn, true, DTA_Masked, false, TAG_DONE);
|
||||
|
||||
// The fire may not always stabilize, so the wipe is forced to end
|
||||
// after an arbitrary maximum time.
|
||||
return done || (BurnTime > 40);
|
||||
}
|
||||
|
||||
|
||||
void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stopsound, std::function<void()> overlaydrawer)
|
||||
{
|
||||
// wipe update
|
||||
uint64_t wipestart, nowtime, diff;
|
||||
bool done;
|
||||
|
||||
GSnd->SetSfxPaused(true, 1);
|
||||
I_FreezeTime(true);
|
||||
twod->End();
|
||||
assert(startimg != nullptr && endimg != nullptr);
|
||||
auto starttex = MakeGameTexture(startimg, nullptr, ETextureType::SWCanvas);
|
||||
auto endtex = MakeGameTexture(endimg, nullptr, ETextureType::SWCanvas);
|
||||
auto wiper = Wiper::Create(wipe_type);
|
||||
wiper->SetTextures(starttex, endtex);
|
||||
|
||||
wipestart = I_msTime();
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
I_WaitVBL(2);
|
||||
nowtime = I_msTime();
|
||||
diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow.
|
||||
} while (diff < 1);
|
||||
wipestart = nowtime;
|
||||
twod->Begin(screen->GetWidth(), screen->GetHeight());
|
||||
done = wiper->Run(1);
|
||||
if (overlaydrawer) overlaydrawer();
|
||||
twod->End();
|
||||
screen->Update();
|
||||
twod->OnFrameDone();
|
||||
|
||||
} while (!done);
|
||||
delete wiper;
|
||||
I_FreezeTime(false);
|
||||
GSnd->SetSfxPaused(false, 1);
|
||||
|
||||
}
|
38
source/common/2d/wipe.h
Executable file
38
source/common/2d/wipe.h
Executable file
|
@ -0,0 +1,38 @@
|
|||
#ifndef __F_WIPE_H__
|
||||
#define __F_WIPE_H__
|
||||
|
||||
#include "stdint.h"
|
||||
#include <functional>
|
||||
|
||||
class FTexture;
|
||||
int wipe_CalcBurn(uint8_t *buffer, int width, int height, int density);
|
||||
|
||||
enum
|
||||
{
|
||||
wipe_None, // don't bother
|
||||
wipe_Melt, // weird screen melt
|
||||
wipe_Burn, // fade in shape of fire
|
||||
wipe_Fade, // crossfade from old to new
|
||||
wipe_NUMWIPES
|
||||
};
|
||||
|
||||
class Wiper
|
||||
{
|
||||
protected:
|
||||
FGameTexture *startScreen = nullptr, *endScreen = nullptr;
|
||||
public:
|
||||
virtual ~Wiper();
|
||||
virtual bool Run(int ticks) = 0;
|
||||
virtual void SetTextures(FGameTexture *startscreen, FGameTexture *endscreen)
|
||||
{
|
||||
startScreen = startscreen;
|
||||
endScreen = endscreen;
|
||||
}
|
||||
|
||||
static Wiper *Create(int type);
|
||||
};
|
||||
|
||||
void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stopsound, std::function<void()> overlaydrawer);
|
||||
|
||||
|
||||
#endif
|
|
@ -200,7 +200,8 @@ static void SetupWgOpn()
|
|||
|
||||
static void SetupDMXGUS()
|
||||
{
|
||||
int lump = fileSystem.CheckNumForFullName("DMXGUS");
|
||||
int lump = fileSystem.CheckNumForName("DMXGUSC", ns_global);
|
||||
if (lump < 0) lump = fileSystem.CheckNumForName("DMXGUS", ns_global);
|
||||
if (lump < 0)
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -194,6 +194,7 @@ FileReader FSF2Reader::OpenFile(const char *name)
|
|||
|
||||
FZipPatReader::FZipPatReader(const char *filename)
|
||||
{
|
||||
mAllowAbsolutePaths = true;
|
||||
resf = FResourceFile::OpenResourceFile(filename, true);
|
||||
}
|
||||
|
||||
|
@ -218,6 +219,7 @@ FileReader FZipPatReader::OpenFile(const char *name)
|
|||
return lump->NewReader();
|
||||
}
|
||||
}
|
||||
fr.OpenFile(name);
|
||||
return fr;
|
||||
}
|
||||
|
||||
|
@ -478,13 +480,6 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed
|
|||
}
|
||||
}
|
||||
|
||||
auto sfi = FindSoundFont(name, allowed);
|
||||
if (sfi != nullptr)
|
||||
{
|
||||
if (sfi->type == SF_SF2) return new FSF2Reader(sfi->mFilename);
|
||||
else return new FZipPatReader(sfi->mFilename);
|
||||
}
|
||||
// The sound font collection did not yield any good results.
|
||||
// Next check if the file is a .sf file
|
||||
if (allowed & SF_SF2)
|
||||
{
|
||||
|
@ -500,6 +495,7 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed
|
|||
}
|
||||
}
|
||||
}
|
||||
// Next check if the file is a resource file (it should contains gus patches and a timidity.cfg file)
|
||||
if (allowed & SF_GUS)
|
||||
{
|
||||
FileReader fr;
|
||||
|
@ -523,6 +519,13 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed
|
|||
return new FPatchSetReader(name);
|
||||
}
|
||||
}
|
||||
// Lastly check in the sound font collection for a specific item or pick the first valid item available.
|
||||
auto sfi = FindSoundFont(name, allowed);
|
||||
if (sfi != nullptr)
|
||||
{
|
||||
if (sfi->type == SF_SF2) return new FSF2Reader(sfi->mFilename);
|
||||
else return new FZipPatReader(sfi->mFilename);
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
|
|
@ -278,7 +278,7 @@ CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL)
|
|||
//==========================================================================
|
||||
|
||||
|
||||
CUSTOM_CVAR(String, midi_config, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||
CUSTOM_CVAR(String, midi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||
{
|
||||
FORWARD_STRING_CVAR(gus_config);
|
||||
}
|
||||
|
|
|
@ -55,9 +55,6 @@ struct FLatchedValue
|
|||
|
||||
static TArray<FLatchedValue> LatchedValues;
|
||||
|
||||
bool FBaseCVar::m_DoNoSet = false;
|
||||
bool FBaseCVar::m_UseCallback = false;
|
||||
|
||||
FBaseCVar *CVars = NULL;
|
||||
|
||||
int cvar_defflags;
|
||||
|
@ -523,6 +520,7 @@ void FBaseCVar::EnableNoSet ()
|
|||
|
||||
void FBaseCVar::EnableCallbacks ()
|
||||
{
|
||||
m_inEnable = true;
|
||||
m_UseCallback = true;
|
||||
FBaseCVar *cvar = CVars;
|
||||
|
||||
|
@ -534,6 +532,7 @@ void FBaseCVar::EnableCallbacks ()
|
|||
}
|
||||
cvar = cvar->m_Next;
|
||||
}
|
||||
m_inEnable = false;
|
||||
}
|
||||
|
||||
void FBaseCVar::DisableCallbacks ()
|
||||
|
|
|
@ -210,14 +210,17 @@ protected:
|
|||
uint32_t Flags;
|
||||
bool inCallback = false;
|
||||
|
||||
public:
|
||||
static inline bool m_inEnable = false;
|
||||
|
||||
private:
|
||||
FBaseCVar (const FBaseCVar &var) = delete;
|
||||
FBaseCVar (const char *name, uint32_t flags);
|
||||
void (*m_Callback)(FBaseCVar &);
|
||||
FBaseCVar *m_Next;
|
||||
|
||||
static bool m_UseCallback;
|
||||
static bool m_DoNoSet;
|
||||
static inline bool m_UseCallback = false;
|
||||
static inline bool m_DoNoSet = false;
|
||||
|
||||
void *m_ExtraDataPointer;
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
#include "s_music.h"
|
||||
#include "m_argv.h"
|
||||
#include "i_interface.h"
|
||||
#include "gamecontrol.h"
|
||||
|
||||
CVAR(Bool, inter_subtitles, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||
|
||||
|
@ -313,16 +312,14 @@ bool StartCutscene(CutsceneDef& cs, int flags, const CompletionFunc& completion_
|
|||
cs.Create(runner);
|
||||
if (!ScreenJobValidate())
|
||||
{
|
||||
runner->Destroy();
|
||||
runner = nullptr;
|
||||
DeleteScreenJob();
|
||||
return false;
|
||||
}
|
||||
if (sysCallbacks.StartCutscene) sysCallbacks.StartCutscene(flags & SJ_BLOCKUI);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (runner) runner->Destroy();
|
||||
runner = nullptr;
|
||||
DeleteScreenJob();
|
||||
throw;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -115,7 +115,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer)
|
|||
//
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
static uint32_t Zip_FindCentralDir(FileReader &fin)
|
||||
static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64)
|
||||
{
|
||||
unsigned char buf[BUFREADCOMMENT + 4];
|
||||
uint32_t FileSize;
|
||||
|
@ -145,15 +145,18 @@ static uint32_t Zip_FindCentralDir(FileReader &fin)
|
|||
|
||||
for (i = (int)uReadSize - 3; (i--) > 0;)
|
||||
{
|
||||
if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6)
|
||||
if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6 && !*zip64 && uPosFound == 0)
|
||||
{
|
||||
*zip64 = false;
|
||||
uPosFound = uReadPos + i;
|
||||
break;
|
||||
}
|
||||
if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 6 && buf[i+3] == 6)
|
||||
{
|
||||
*zip64 = true;
|
||||
uPosFound = uReadPos + i;
|
||||
return uPosFound;
|
||||
}
|
||||
}
|
||||
|
||||
if (uPosFound != 0)
|
||||
break;
|
||||
}
|
||||
return uPosFound;
|
||||
}
|
||||
|
@ -172,8 +175,8 @@ FZipFile::FZipFile(const char * filename, FileReader &file)
|
|||
|
||||
bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
||||
{
|
||||
uint32_t centraldir = Zip_FindCentralDir(Reader);
|
||||
FZipEndOfCentralDirectory info;
|
||||
bool zip64 = false;
|
||||
uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64);
|
||||
int skipped = 0;
|
||||
|
||||
Lumps = NULL;
|
||||
|
@ -184,25 +187,50 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Read the central directory info.
|
||||
Reader.Seek(centraldir, FileReader::SeekSet);
|
||||
Reader.Read(&info, sizeof(FZipEndOfCentralDirectory));
|
||||
|
||||
// No multi-disk zips!
|
||||
if (info.NumEntries != info.NumEntriesOnAllDisks ||
|
||||
info.FirstDisk != 0 || info.DiskNumber != 0)
|
||||
uint64_t dirsize, DirectoryOffset;
|
||||
if (!zip64)
|
||||
{
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
FZipEndOfCentralDirectory info;
|
||||
// Read the central directory info.
|
||||
Reader.Seek(centraldir, FileReader::SeekSet);
|
||||
Reader.Read(&info, sizeof(FZipEndOfCentralDirectory));
|
||||
|
||||
NumLumps = LittleShort(info.NumEntries);
|
||||
// No multi-disk zips!
|
||||
if (info.NumEntries != info.NumEntriesOnAllDisks ||
|
||||
info.FirstDisk != 0 || info.DiskNumber != 0)
|
||||
{
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
|
||||
NumLumps = LittleShort(info.NumEntries);
|
||||
dirsize = LittleLong(info.DirectorySize);
|
||||
DirectoryOffset = LittleLong(info.DirectoryOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
FZipEndOfCentralDirectory64 info;
|
||||
// Read the central directory info.
|
||||
Reader.Seek(centraldir, FileReader::SeekSet);
|
||||
Reader.Read(&info, sizeof(FZipEndOfCentralDirectory64));
|
||||
|
||||
// No multi-disk zips!
|
||||
if (info.NumEntries != info.NumEntriesOnAllDisks ||
|
||||
info.FirstDisk != 0 || info.DiskNumber != 0)
|
||||
{
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
|
||||
NumLumps = info.NumEntries;
|
||||
dirsize = info.DirectorySize;
|
||||
DirectoryOffset = info.DirectoryOffset;
|
||||
}
|
||||
Lumps = new FZipLump[NumLumps];
|
||||
|
||||
// Load the entire central directory. Too bad that this contains variable length entries...
|
||||
int dirsize = LittleLong(info.DirectorySize);
|
||||
void *directory = malloc(dirsize);
|
||||
Reader.Seek(LittleLong(info.DirectoryOffset), FileReader::SeekSet);
|
||||
Reader.Seek(DirectoryOffset, FileReader::SeekSet);
|
||||
Reader.Read(directory, dirsize);
|
||||
|
||||
char *dirptr = (char*)directory;
|
||||
|
@ -305,7 +333,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
if (name0.IsNotEmpty()) name = name.Mid(name0.Len());
|
||||
|
||||
// skip Directories
|
||||
if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0))
|
||||
if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0))
|
||||
{
|
||||
skipped++;
|
||||
continue;
|
||||
|
@ -335,9 +363,39 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
|
||||
FixPathSeperator(name);
|
||||
name.ToLower();
|
||||
|
||||
uint32_t UncompressedSize =LittleLong(zip_fh->UncompressedSize32);
|
||||
uint32_t CompressedSize = LittleLong(zip_fh->CompressedSize32);
|
||||
uint64_t LocalHeaderOffset = LittleLong(zip_fh->LocalHeaderOffset32);
|
||||
if (zip_fh->ExtraLength > 0)
|
||||
{
|
||||
uint8_t* rawext = (uint8_t*)zip_fh + sizeof(*zip_fh) + zip_fh->NameLength;
|
||||
uint32_t ExtraLength = LittleLong(zip_fh->ExtraLength);
|
||||
|
||||
while (ExtraLength > 0)
|
||||
{
|
||||
auto zip_64 = (FZipCentralDirectoryInfo64BitExt*)rawext;
|
||||
uint32_t BlockLength = LittleLong(zip_64->Length);
|
||||
rawext += BlockLength + 4;
|
||||
ExtraLength -= BlockLength + 4;
|
||||
if (LittleLong(zip_64->Type) == 1 && BlockLength >= 0x18)
|
||||
{
|
||||
if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff)
|
||||
{
|
||||
// The file system is limited to 32 bit file sizes;
|
||||
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is too large.\n", FileName.GetChars(), name.GetChars());
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
UncompressedSize = (uint32_t)zip_64->UncompressedSize;
|
||||
CompressedSize = (uint32_t)zip_64->CompressedSize;
|
||||
LocalHeaderOffset = zip_64->LocalHeaderOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lump_p->LumpNameSetup(name);
|
||||
lump_p->LumpSize = LittleLong(zip_fh->UncompressedSize);
|
||||
lump_p->LumpSize = UncompressedSize;
|
||||
lump_p->Owner = this;
|
||||
// The start of the Reader will be determined the first time it is accessed.
|
||||
lump_p->Flags = LUMPF_FULLPATH;
|
||||
|
@ -346,8 +404,8 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
if (lump_p->Method != METHOD_STORED) lump_p->Flags |= LUMPF_COMPRESSED;
|
||||
lump_p->GPFlags = zip_fh->Flags;
|
||||
lump_p->CRC32 = zip_fh->CRC32;
|
||||
lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize);
|
||||
lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset);
|
||||
lump_p->CompressedSize = CompressedSize;
|
||||
lump_p->Position = LocalHeaderOffset;
|
||||
lump_p->CheckEmbedded(filter);
|
||||
|
||||
lump_p++;
|
||||
|
@ -585,15 +643,15 @@ int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompress
|
|||
dir.ModTime = LittleShort(dostime.first);
|
||||
dir.ModDate = LittleShort(dostime.second);
|
||||
dir.CRC32 = content.mCRC32;
|
||||
dir.CompressedSize = LittleLong(content.mCompressedSize);
|
||||
dir.UncompressedSize = LittleLong(content.mSize);
|
||||
dir.CompressedSize32 = LittleLong(content.mCompressedSize);
|
||||
dir.UncompressedSize32 = LittleLong(content.mSize);
|
||||
dir.NameLength = LittleShort((unsigned short)strlen(filename));
|
||||
dir.ExtraLength = 0;
|
||||
dir.CommentLength = 0;
|
||||
dir.StartingDiskNumber = 0;
|
||||
dir.InternalAttributes = 0;
|
||||
dir.ExternalAttributes = 0;
|
||||
dir.LocalHeaderOffset = LittleLong(position);
|
||||
dir.LocalHeaderOffset32 = LittleLong(position);
|
||||
|
||||
if (zip_file->Write(&dir, sizeof(dir)) != sizeof(dir) ||
|
||||
zip_file->Write(filename, strlen(filename)) != strlen(filename))
|
||||
|
|
|
@ -15,7 +15,7 @@ struct FZipLump : public FResourceLump
|
|||
uint8_t Method;
|
||||
bool NeedFileStart;
|
||||
int CompressedSize;
|
||||
int Position;
|
||||
int64_t Position;
|
||||
unsigned CRC32;
|
||||
|
||||
virtual FileReader *GetReader();
|
||||
|
|
|
@ -17,6 +17,22 @@ struct FZipEndOfCentralDirectory
|
|||
uint16_t ZipCommentLength;
|
||||
} FORCE_PACKED;
|
||||
|
||||
struct FZipEndOfCentralDirectory64
|
||||
{
|
||||
uint32_t Magic;
|
||||
uint64_t StructSize;
|
||||
uint16_t VersionMadeBy;
|
||||
uint16_t VersionNeeded;
|
||||
uint32_t DiskNumber;
|
||||
uint32_t FirstDisk;
|
||||
uint64_t NumEntries;
|
||||
uint64_t NumEntriesOnAllDisks;
|
||||
uint64_t DirectorySize;
|
||||
uint64_t DirectoryOffset;
|
||||
uint16_t ZipCommentLength;
|
||||
} FORCE_PACKED;
|
||||
|
||||
|
||||
// FZipFileInfo
|
||||
struct FZipCentralDirectoryInfo
|
||||
{
|
||||
|
@ -28,18 +44,28 @@ struct FZipCentralDirectoryInfo
|
|||
uint16_t ModTime;
|
||||
uint16_t ModDate;
|
||||
uint32_t CRC32;
|
||||
uint32_t CompressedSize;
|
||||
uint32_t UncompressedSize;
|
||||
uint32_t CompressedSize32;
|
||||
uint32_t UncompressedSize32;
|
||||
uint16_t NameLength;
|
||||
uint16_t ExtraLength;
|
||||
uint16_t CommentLength;
|
||||
uint16_t StartingDiskNumber;
|
||||
uint16_t InternalAttributes;
|
||||
uint32_t ExternalAttributes;
|
||||
uint32_t LocalHeaderOffset;
|
||||
uint32_t LocalHeaderOffset32;
|
||||
// file name and other variable length info follows
|
||||
} FORCE_PACKED;
|
||||
|
||||
struct FZipCentralDirectoryInfo64BitExt
|
||||
{
|
||||
uint16_t Type;
|
||||
uint16_t Length;
|
||||
uint64_t UncompressedSize;
|
||||
uint64_t CompressedSize;
|
||||
uint64_t LocalHeaderOffset;
|
||||
uint32_t DiskNo;
|
||||
} FORCE_PACKED;
|
||||
|
||||
// FZipLocalHeader
|
||||
struct FZipLocalFileHeader
|
||||
{
|
||||
|
@ -57,7 +83,6 @@ struct FZipLocalFileHeader
|
|||
// file name and other variable length info follows
|
||||
} FORCE_PACKED;
|
||||
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#define ZIP_LOCALFILE MAKE_ID('P','K',3,4)
|
||||
|
|
|
@ -753,6 +753,12 @@ static void ParseListMenu(FScanner &sc)
|
|||
desc->mFromEngine = fileSystem.GetFileContainer(sc.LumpNum) == 0; // flags menu if the definition is from the IWAD.
|
||||
desc->mVirtWidth = -2;
|
||||
desc->mCustomSizeSet = false;
|
||||
if (DefaultListMenuSettings->mCustomSizeSet)
|
||||
{
|
||||
desc->mVirtHeight = DefaultListMenuSettings->mVirtHeight;
|
||||
desc->mVirtWidth = DefaultListMenuSettings->mVirtWidth;
|
||||
desc->mCustomSizeSet = true;
|
||||
}
|
||||
|
||||
ParseListMenuBody(sc, desc, -1);
|
||||
ReplaceMenu(sc, desc);
|
||||
|
@ -1496,7 +1502,7 @@ static void InitMusicMenus()
|
|||
{
|
||||
DMenuDescriptor **advmenu = MenuDescriptors.CheckKey("AdvSoundOptions");
|
||||
auto soundfonts = sfmanager.GetList();
|
||||
std::tuple<const char *, int, const char *> sfmenus[] = { std::make_tuple("GusConfigMenu", SF_SF2 | SF_GUS, "midi_config"),
|
||||
std::tuple<const char *, int, const char *> sfmenus[] = { std::make_tuple("GusConfigMenu", SF_GUS, "midi_config"),
|
||||
std::make_tuple("WildMidiConfigMenu", SF_GUS, "wildmidi_config"),
|
||||
std::make_tuple("TimidityConfigMenu", SF_SF2 | SF_GUS, "timidity_config"),
|
||||
std::make_tuple("FluidPatchsetMenu", SF_SF2, "fluid_patchset"),
|
||||
|
|
|
@ -459,6 +459,7 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, SavegameCount)
|
|||
|
||||
FSaveGameNode *FSavegameManagerBase::GetSavegame(int i)
|
||||
{
|
||||
if ((unsigned)i >= SaveGames.Size()) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Bad savegame index");
|
||||
return SaveGames[i];
|
||||
}
|
||||
|
||||
|
|
|
@ -71,17 +71,17 @@ void M_GetMacSearchDirectories(FString& user_docs, FString& user_app_support, FS
|
|||
? "~/" GAME_DIR
|
||||
: (path + "/" GAME_DIR);
|
||||
|
||||
#define LIBRARY_APPSUPPORT "/Library/Application Support"
|
||||
#define LIBRARY_APPSUPPORT "/Library/Application Support/"
|
||||
|
||||
path = M_GetMacAppSupportPath();
|
||||
user_app_support = path.IsEmpty()
|
||||
? "~" LIBRARY_APPSUPPORT
|
||||
: (path);
|
||||
? "~" LIBRARY_APPSUPPORT GAME_DIR
|
||||
: (path + "/" GAME_DIR);
|
||||
|
||||
path = GetSpecialPath(NSApplicationSupportDirectory, YES, NSLocalDomainMask);
|
||||
local_app_support = path.IsEmpty()
|
||||
? LIBRARY_APPSUPPORT
|
||||
: (path);
|
||||
? LIBRARY_APPSUPPORT GAME_DIR
|
||||
: (path + "/" GAME_DIR);
|
||||
|
||||
#undef LIBRARY_APPSUPPORT
|
||||
}
|
||||
|
|
|
@ -362,6 +362,29 @@ void OpenGLFrameBuffer::BlurScene(float amount)
|
|||
GLRenderer->BlurScene(amount);
|
||||
}
|
||||
|
||||
void OpenGLFrameBuffer::InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData)
|
||||
{
|
||||
if (LMTextureData.Size() > 0)
|
||||
{
|
||||
GLint activeTex = 0;
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
|
||||
glActiveTexture(GL_TEXTURE0 + 17);
|
||||
|
||||
if (GLRenderer->mLightMapID == 0)
|
||||
glGenTextures(1, (GLuint*)&GLRenderer->mLightMapID);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, GLRenderer->mLightMapID);
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB16F, LMTextureSize, LMTextureSize, LMTextureCount, 0, GL_RGB, GL_HALF_FLOAT, &LMTextureData[0]);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
|
||||
glActiveTexture(activeTex);
|
||||
|
||||
LMTextureData.Reset(); // We no longer need this, release the memory
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLFrameBuffer::SetViewportRects(IntRect *bounds)
|
||||
{
|
||||
Super::SetViewportRects(bounds);
|
||||
|
|
|
@ -50,6 +50,8 @@ public:
|
|||
IIndexBuffer *CreateIndexBuffer() override;
|
||||
IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override;
|
||||
|
||||
void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData) override;
|
||||
|
||||
// Retrieves a buffer containing image data for a screenshot.
|
||||
// Hint: Pitch can be negative for upside-down images, in which case buffer
|
||||
// points to the last row in the buffer, which will be the first row output.
|
||||
|
|
|
@ -61,6 +61,8 @@ public:
|
|||
FPresent3DRowShader *mPresent3dRowShader = nullptr;
|
||||
FShadowMapShader *mShadowMapShader = nullptr;
|
||||
|
||||
int mLightMapID = 0;
|
||||
|
||||
//FRotator mAngles;
|
||||
|
||||
FGLRenderer(OpenGLFrameBuffer *fb);
|
||||
|
|
|
@ -300,6 +300,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
// textures
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D ShadowMap;
|
||||
uniform sampler2DArray LightMap;
|
||||
uniform sampler2D texture2;
|
||||
uniform sampler2D texture3;
|
||||
uniform sampler2D texture4;
|
||||
|
@ -621,11 +622,14 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
char stringbuf[20];
|
||||
mysnprintf(stringbuf, 20, "texture%d", i);
|
||||
tempindex = glGetUniformLocation(hShader, stringbuf);
|
||||
if (tempindex > 0) glUniform1i(tempindex, i - 1);
|
||||
if (tempindex != -1) glUniform1i(tempindex, i - 1);
|
||||
}
|
||||
|
||||
int shadowmapindex = glGetUniformLocation(hShader, "ShadowMap");
|
||||
if (shadowmapindex > 0) glUniform1i(shadowmapindex, 16);
|
||||
if (shadowmapindex != -1) glUniform1i(shadowmapindex, 16);
|
||||
|
||||
int lightmapindex = glGetUniformLocation(hShader, "LightMap");
|
||||
if (lightmapindex != -1) glUniform1i(lightmapindex, 17);
|
||||
|
||||
glUseProgram(0);
|
||||
return linked;
|
||||
|
|
|
@ -207,29 +207,28 @@ void GLBuffer::Unlock()
|
|||
}
|
||||
|
||||
void GLBuffer::Resize(size_t newsize)
|
||||
{
|
||||
assert(!nomap); // only mappable buffers can be resized.
|
||||
if (newsize > buffersize && !nomap)
|
||||
{
|
||||
if (newsize > buffersize)
|
||||
{
|
||||
/*
|
||||
// reallocate the buffer with twice the size
|
||||
unsigned int oldbuffer = mBufferId;
|
||||
if (isData)
|
||||
{
|
||||
// Create new bigger memory
|
||||
char* memoryNew = (char*)(new uint64_t[newsize / 8 + 16]);
|
||||
|
||||
// first unmap the old buffer
|
||||
Bind();
|
||||
glUnmapBuffer(mUseType);
|
||||
// Copy old data
|
||||
memcpy(memoryNew, memory, buffersize);
|
||||
|
||||
glGenBuffers(1, &mBufferId);
|
||||
SetData(newsize, nullptr, false);
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, oldbuffer);
|
||||
// Delete old memory
|
||||
delete[] memory;
|
||||
|
||||
// copy contents and delete the old buffer.
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, mUseType, 0, 0, buffersize);
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, 0);
|
||||
glDeleteBuffers(1, &oldbuffer);
|
||||
buffersize = newsize;
|
||||
InvalidateBufferState();
|
||||
*/
|
||||
memory = memoryNew;
|
||||
|
||||
buffersize = newsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ enum
|
|||
VATTR_VERTEX2,
|
||||
VATTR_NORMAL,
|
||||
VATTR_NORMAL2,
|
||||
|
||||
VATTR_LIGHTMAP,
|
||||
VATTR_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -93,10 +93,11 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr):
|
|||
|
||||
static const FVertexBufferAttribute format[] = {
|
||||
{ 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) },
|
||||
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }
|
||||
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) },
|
||||
{ 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FFlatVertex, lu) },
|
||||
};
|
||||
|
||||
mVertexBufferPipeline[n]->SetFormat(1, 2, sizeof(FFlatVertex), format);
|
||||
mVertexBufferPipeline[n]->SetFormat(1, 3, sizeof(FFlatVertex), format);
|
||||
}
|
||||
|
||||
mVertexBuffer = mVertexBufferPipeline[mPipelinePos];
|
||||
|
|
|
@ -14,6 +14,8 @@ struct FFlatVertex
|
|||
{
|
||||
float x, z, y; // world position
|
||||
float u, v; // texture coordinates
|
||||
float lu, lv; // lightmap texture coordinates
|
||||
float lindex; // lightmap texture index
|
||||
|
||||
void Set(float xx, float zz, float yy, float uu, float vv)
|
||||
{
|
||||
|
@ -22,6 +24,19 @@ struct FFlatVertex
|
|||
y = yy;
|
||||
u = uu;
|
||||
v = vv;
|
||||
lindex = -1.0f;
|
||||
}
|
||||
|
||||
void Set(float xx, float zz, float yy, float uu, float vv, float llu, float llv, float llindex)
|
||||
{
|
||||
x = xx;
|
||||
z = zz;
|
||||
y = yy;
|
||||
u = uu;
|
||||
v = vv;
|
||||
lu = llu;
|
||||
lv = llv;
|
||||
lindex = llindex;
|
||||
}
|
||||
|
||||
void SetVertex(float _x, float _y, float _z = 0)
|
||||
|
|
|
@ -46,10 +46,11 @@ FModelVertexBuffer::FModelVertexBuffer(bool needindex, bool singleframe)
|
|||
{ 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FModelVertex, x) },
|
||||
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FModelVertex, u) },
|
||||
{ 0, VATTR_NORMAL, VFmt_Packed_A2R10G10B10, (int)myoffsetof(FModelVertex, packedNormal) },
|
||||
{ 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FModelVertex, lu) },
|
||||
{ 1, VATTR_VERTEX2, VFmt_Float3, (int)myoffsetof(FModelVertex, x) },
|
||||
{ 1, VATTR_NORMAL2, VFmt_Packed_A2R10G10B10, (int)myoffsetof(FModelVertex, packedNormal) }
|
||||
};
|
||||
mVertexBuffer->SetFormat(2, 5, sizeof(FModelVertex), format);
|
||||
mVertexBuffer->SetFormat(2, 6, sizeof(FModelVertex), format);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -894,7 +894,7 @@ void PPShadowMap::Update(PPRenderState* renderstate)
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CVAR(Bool, gl_custompost, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||
CVAR(Bool, gl_custompost, true, 0)
|
||||
|
||||
void PPCustomShaders::Run(PPRenderState *renderstate, FString target)
|
||||
{
|
||||
|
|
|
@ -7,6 +7,8 @@ struct FModelVertex
|
|||
float x, y, z; // world position
|
||||
float u, v; // texture coordinates
|
||||
unsigned packedNormal; // normal vector as GL_INT_2_10_10_10_REV.
|
||||
float lu, lv; // lightmap texture coordinates
|
||||
float lindex; // lightmap texture index
|
||||
|
||||
void Set(float xx, float yy, float zz, float uu, float vv)
|
||||
{
|
||||
|
@ -15,6 +17,9 @@ struct FModelVertex
|
|||
z = zz;
|
||||
u = uu;
|
||||
v = vv;
|
||||
lu = 0.0f;
|
||||
lv = 0.0f;
|
||||
lindex = -1.0f;
|
||||
}
|
||||
|
||||
void SetNormal(float nx, float ny, float nz)
|
||||
|
|
|
@ -29,10 +29,4 @@ void I_PolyPresentUnlock(int x, int y, int w, int h);
|
|||
void I_PolyPresentDeinit();
|
||||
|
||||
|
||||
// Pause a bit.
|
||||
// [RH] Despite the name, it apparently never waited for the VBL, even in
|
||||
// the original DOS version (if the Heretic/Hexen source is any indicator).
|
||||
void I_WaitVBL(int count);
|
||||
|
||||
|
||||
#endif // __I_VIDEO_H__
|
||||
|
|
|
@ -287,7 +287,7 @@ void PolyRenderState::Apply()
|
|||
|
||||
PolyPushConstants constants;
|
||||
constants.uFogEnabled = fogset;
|
||||
constants.uTextureMode = GetTextureModeAndFlags(mTempTM);
|
||||
constants.uTextureMode = (mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode);
|
||||
constants.uLightDist = mLightParms[0];
|
||||
constants.uLightFactor = mLightParms[1];
|
||||
constants.uFogDensity = mLightParms[2];
|
||||
|
|
|
@ -281,6 +281,12 @@ void V_UpdateModeSize (int width, int height)
|
|||
CleanHeight = screen->GetHeight() / CleanYfac;
|
||||
|
||||
int w = screen->GetWidth();
|
||||
int h = screen->GetHeight();
|
||||
|
||||
// clamp screen aspect ratio to 17:10, for anything wider the width will be reduced
|
||||
double aspect = (double)w / h;
|
||||
if (aspect > 1.7) w = int(w * 1.7 / aspect);
|
||||
|
||||
int factor;
|
||||
if (w < 640) factor = 1;
|
||||
else if (w >= 1024 && w < 1280) factor = 2;
|
||||
|
|
|
@ -220,6 +220,8 @@ public:
|
|||
virtual int GetClientHeight() = 0;
|
||||
virtual void BlurScene(float amount) {}
|
||||
|
||||
virtual void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData) {}
|
||||
|
||||
// Interface to hardware rendering resources
|
||||
virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; }
|
||||
virtual IIndexBuffer *CreateIndexBuffer() { return nullptr; }
|
||||
|
|
|
@ -78,6 +78,7 @@ void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int scen
|
|||
CreateScene(width, height, samples);
|
||||
|
||||
CreateShadowmap();
|
||||
CreateLightmapSampler();
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
@ -264,3 +265,41 @@ void VkRenderBuffers::CreateShadowmap()
|
|||
ShadowmapSampler->SetDebugName("VkRenderBuffers.ShadowmapSampler");
|
||||
}
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateLightmapSampler()
|
||||
{
|
||||
if (!Lightmap.Image)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(1, 1);
|
||||
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
Lightmap.Image = builder.create(fb->device);
|
||||
Lightmap.Image->SetDebugName("VkRenderBuffers.Lightmap");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
|
||||
viewbuilder.setImage(Lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
Lightmap.View = viewbuilder.create(fb->device);
|
||||
Lightmap.View->SetDebugName("VkRenderBuffers.LightmapView");
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
|
||||
barrier.execute(fb->GetDrawCommands());
|
||||
}
|
||||
|
||||
if (!LightmapSampler)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
SamplerBuilder builder;
|
||||
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR);
|
||||
builder.setMinFilter(VK_FILTER_LINEAR);
|
||||
builder.setMagFilter(VK_FILTER_LINEAR);
|
||||
builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
|
||||
LightmapSampler = builder.create(fb->device);
|
||||
LightmapSampler->SetDebugName("VkRenderBuffers.LightmapSampler");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@ public:
|
|||
VkTextureImage Shadowmap;
|
||||
std::unique_ptr<VulkanSampler> ShadowmapSampler;
|
||||
|
||||
VkTextureImage Lightmap;
|
||||
std::unique_ptr<VulkanSampler> LightmapSampler;
|
||||
|
||||
private:
|
||||
void CreatePipeline(int width, int height);
|
||||
void CreateScene(int width, int height, VkSampleCountFlagBits samples);
|
||||
|
@ -40,6 +43,7 @@ private:
|
|||
void CreateSceneFog(int width, int height, VkSampleCountFlagBits samples);
|
||||
void CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples);
|
||||
void CreateShadowmap();
|
||||
void CreateLightmapSampler();
|
||||
VkSampleCountFlagBits GetBestSampleCount();
|
||||
|
||||
int mWidth = 0;
|
||||
|
|
|
@ -130,6 +130,7 @@ void VkRenderPassManager::CreateDynamicSetLayout()
|
|||
builder.addBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
DynamicSetLayout = builder.create(GetVulkanFrameBuffer()->device);
|
||||
DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout");
|
||||
}
|
||||
|
@ -177,7 +178,7 @@ void VkRenderPassManager::CreateDescriptorPool()
|
|||
DescriptorPoolBuilder builder;
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3);
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1);
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2);
|
||||
builder.setMaxSets(1);
|
||||
DynamicDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
|
||||
DynamicDescriptorPool->SetDebugName("VkRenderPassManager.DynamicDescriptorPool");
|
||||
|
@ -249,6 +250,7 @@ void VkRenderPassManager::UpdateDynamicSet()
|
|||
update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO));
|
||||
update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO));
|
||||
update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->Shadowmap.View.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.addCombinedImageSampler(DynamicSet.get(), 5, fb->GetBuffers()->Lightmap.View.get(), fb->GetBuffers()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.updateSets(fb->device);
|
||||
}
|
||||
|
||||
|
@ -376,7 +378,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
VK_FORMAT_A2B10G10R10_SNORM_PACK32
|
||||
};
|
||||
|
||||
bool inputLocations[6] = { false, false, false, false, false, false };
|
||||
bool inputLocations[7] = { false, false, false, false, false, false, false };
|
||||
|
||||
for (size_t i = 0; i < vfmt.Attrs.size(); i++)
|
||||
{
|
||||
|
@ -386,7 +388,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
}
|
||||
|
||||
// Vulkan requires an attribute binding for each location specified in the shader
|
||||
for (int i = 0; i < 6; i++)
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (!inputLocations[i])
|
||||
builder.addVertexAttribute(i, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
|
||||
|
|
|
@ -172,6 +172,7 @@ static const char *shaderBindings = R"(
|
|||
};
|
||||
|
||||
layout(set = 0, binding = 4) uniform sampler2D ShadowMap;
|
||||
layout(set = 0, binding = 5) uniform sampler2DArray LightMap;
|
||||
|
||||
// textures
|
||||
layout(set = 1, binding = 0) uniform sampler2D tex;
|
||||
|
|
|
@ -38,7 +38,7 @@ class ImageBuilder
|
|||
public:
|
||||
ImageBuilder();
|
||||
|
||||
void setSize(int width, int height, int miplevels = 1);
|
||||
void setSize(int width, int height, int miplevels = 1, int arrayLayers = 1);
|
||||
void setSamples(VkSampleCountFlagBits samples);
|
||||
void setFormat(VkFormat format);
|
||||
void setUsage(VkImageUsageFlags imageUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0);
|
||||
|
@ -60,6 +60,7 @@ class ImageViewBuilder
|
|||
public:
|
||||
ImageViewBuilder();
|
||||
|
||||
void setType(VkImageViewType type);
|
||||
void setImage(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
|
||||
std::unique_ptr<VulkanImageView> create(VulkanDevice *device);
|
||||
|
@ -374,11 +375,12 @@ inline ImageBuilder::ImageBuilder()
|
|||
imageInfo.flags = 0;
|
||||
}
|
||||
|
||||
inline void ImageBuilder::setSize(int width, int height, int mipLevels)
|
||||
inline void ImageBuilder::setSize(int width, int height, int mipLevels, int arrayLayers)
|
||||
{
|
||||
imageInfo.extent.width = width;
|
||||
imageInfo.extent.height = height;
|
||||
imageInfo.mipLevels = mipLevels;
|
||||
imageInfo.arrayLayers = arrayLayers;
|
||||
}
|
||||
|
||||
inline void ImageBuilder::setSamples(VkSampleCountFlagBits samples)
|
||||
|
@ -447,7 +449,7 @@ inline std::unique_ptr<VulkanImage> ImageBuilder::create(VulkanDevice *device, V
|
|||
*allocatedBytes = allocatedInfo.size;
|
||||
}
|
||||
|
||||
return std::make_unique<VulkanImage>(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels);
|
||||
return std::make_unique<VulkanImage>(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels, imageInfo.arrayLayers);
|
||||
}
|
||||
|
||||
inline std::unique_ptr<VulkanImage> ImageBuilder::tryCreate(VulkanDevice *device)
|
||||
|
@ -459,7 +461,7 @@ inline std::unique_ptr<VulkanImage> ImageBuilder::tryCreate(VulkanDevice *device
|
|||
if (result != VK_SUCCESS)
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<VulkanImage>(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels);
|
||||
return std::make_unique<VulkanImage>(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels, imageInfo.arrayLayers);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -474,12 +476,18 @@ inline ImageViewBuilder::ImageViewBuilder()
|
|||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
|
||||
inline void ImageViewBuilder::setType(VkImageViewType type)
|
||||
{
|
||||
viewInfo.viewType = type;
|
||||
}
|
||||
|
||||
inline void ImageViewBuilder::setImage(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask)
|
||||
{
|
||||
viewInfo.image = image->image;
|
||||
viewInfo.format = format;
|
||||
viewInfo.subresourceRange.levelCount = image->mipLevels;
|
||||
viewInfo.subresourceRange.aspectMask = aspectMask;
|
||||
viewInfo.subresourceRange.layerCount = image->layerCount;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<VulkanImageView> ImageViewBuilder::create(VulkanDevice *device)
|
||||
|
|
|
@ -579,6 +579,81 @@ void VulkanFrameBuffer::BeginFrame()
|
|||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData)
|
||||
{
|
||||
if (LMTextureData.Size() > 0)
|
||||
{
|
||||
int w = LMTextureSize;
|
||||
int h = LMTextureSize;
|
||||
int count = LMTextureCount;
|
||||
int pixelsize = 8;
|
||||
auto& lightmap = mActiveRenderBuffers->Lightmap;
|
||||
|
||||
if (lightmap.Image)
|
||||
{
|
||||
FrameDeleteList.Images.push_back(std::move(lightmap.Image));
|
||||
FrameDeleteList.ImageViews.push_back(std::move(lightmap.View));
|
||||
lightmap.reset();
|
||||
}
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(w, h, 1, count);
|
||||
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
lightmap.Image = builder.create(device);
|
||||
lightmap.Image->SetDebugName("VkRenderBuffers.Lightmap");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
|
||||
viewbuilder.setImage(lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
lightmap.View = viewbuilder.create(device);
|
||||
lightmap.View->SetDebugName("VkRenderBuffers.LightmapView");
|
||||
|
||||
auto cmdbuffer = GetTransferCommands();
|
||||
|
||||
int totalSize = w * h * count * pixelsize;
|
||||
|
||||
BufferBuilder bufbuilder;
|
||||
bufbuilder.setSize(totalSize);
|
||||
bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
std::unique_ptr<VulkanBuffer> stagingBuffer = bufbuilder.create(device);
|
||||
stagingBuffer->SetDebugName("VkHardwareTexture.mStagingBuffer");
|
||||
|
||||
uint16_t one = 0x3c00; // half-float 1.0
|
||||
uint16_t* src = &LMTextureData[0];
|
||||
uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize);
|
||||
for (int i = w * h * count; i > 0; i--)
|
||||
{
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = one;
|
||||
}
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, count);
|
||||
imageTransition.execute(cmdbuffer);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = count;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = w;
|
||||
region.imageExtent.height = h;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, count);
|
||||
barrier.execute(cmdbuffer);
|
||||
|
||||
FrameTextureUpload.Buffers.push_back(std::move(stagingBuffer));
|
||||
FrameTextureUpload.TotalSize += totalSize;
|
||||
|
||||
LMTextureData.Reset(); // We no longer need this, release the memory
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::PushGroup(const FString &name)
|
||||
{
|
||||
if (!gpuStatActive)
|
||||
|
|
|
@ -85,6 +85,7 @@ public:
|
|||
void SetTextureFilterMode() override;
|
||||
void StartPrecaching() override;
|
||||
void BeginFrame() override;
|
||||
void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData) override;
|
||||
void BlurScene(float amount) override;
|
||||
void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D) override;
|
||||
void AmbientOccludeScene(float m5) override;
|
||||
|
|
|
@ -79,7 +79,7 @@ private:
|
|||
class VulkanImage
|
||||
{
|
||||
public:
|
||||
VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels);
|
||||
VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels, int layerCount);
|
||||
~VulkanImage();
|
||||
|
||||
void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)image, VK_OBJECT_TYPE_IMAGE); }
|
||||
|
@ -88,6 +88,7 @@ public:
|
|||
int width = 0;
|
||||
int height = 0;
|
||||
int mipLevels = 1;
|
||||
int layerCount = 1;
|
||||
|
||||
void *Map(size_t offset, size_t size);
|
||||
void Unmap();
|
||||
|
@ -989,7 +990,7 @@ inline VulkanFramebuffer::~VulkanFramebuffer()
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline VulkanImage::VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels) : image(image), width(width), height(height), mipLevels(mipLevels), device(device), allocation(allocation)
|
||||
inline VulkanImage::VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels, int layerCount) : image(image), width(width), height(height), mipLevels(mipLevels), layerCount(layerCount), device(device), allocation(allocation)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "vk_imagetransition.h"
|
||||
|
||||
void VkImageTransition::addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout)
|
||||
void VkImageTransition::addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel, int levelCount)
|
||||
{
|
||||
if (image->Layout == targetLayout)
|
||||
return;
|
||||
|
@ -91,7 +91,7 @@ void VkImageTransition::addImage(VkTextureImage *image, VkImageLayout targetLayo
|
|||
I_FatalError("Unimplemented dst image layout transition\n");
|
||||
}
|
||||
|
||||
barrier.addImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask);
|
||||
barrier.addImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask, baseMipLevel, levelCount);
|
||||
needbarrier = true;
|
||||
image->Layout = targetLayout;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
class VkImageTransition
|
||||
{
|
||||
public:
|
||||
void addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout);
|
||||
void addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel = 0, int levelCount = 1);
|
||||
void execute(VulkanCommandBuffer *cmdbuffer);
|
||||
|
||||
private:
|
||||
|
|
|
@ -11156,9 +11156,14 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build)
|
|||
ClearDynamicArray(build);
|
||||
}
|
||||
|
||||
auto zero = build->GetConstantInt(0);
|
||||
auto elementSizeConst = build->GetConstantInt(static_cast<PArray *>(ValueType)->ElementSize);
|
||||
auto arrOffsetReg = build->Registers[REGT_INT].Get(1);
|
||||
build->Emit(OP_LK, arrOffsetReg, build->GetConstantInt(StackOffset));
|
||||
int arrOffsetReg;
|
||||
if (!isDynamicArray)
|
||||
{
|
||||
arrOffsetReg = build->Registers[REGT_POINTER].Get(1);
|
||||
build->Emit(OP_ADDA_RK, arrOffsetReg, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
|
||||
}
|
||||
|
||||
for (auto v : values)
|
||||
{
|
||||
|
@ -11166,6 +11171,7 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build)
|
|||
|
||||
if (isDynamicArray)
|
||||
{
|
||||
emitval.Free(build);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -11178,61 +11184,48 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build)
|
|||
if (emitval.Konst)
|
||||
{
|
||||
auto constval = static_cast<FxConstant *>(v);
|
||||
int regNum = build->Registers[regtype].Get(1);
|
||||
auto regNum = build->Registers[regtype].Get(1);
|
||||
switch (regtype)
|
||||
{
|
||||
default:
|
||||
case REGT_INT:
|
||||
build->Emit(OP_LK, regNum, build->GetConstantInt(constval->GetValue().GetInt()));
|
||||
build->Emit(OP_SW_R, build->FramePointer.RegNum, regNum, arrOffsetReg);
|
||||
build->Emit(OP_LK, regNum, emitval.RegNum);
|
||||
build->Emit(OP_SW, arrOffsetReg, regNum, zero);
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
build->Emit(OP_LKF, regNum, build->GetConstantFloat(constval->GetValue().GetFloat()));
|
||||
build->Emit(OP_SDP_R, build->FramePointer.RegNum, regNum, arrOffsetReg);
|
||||
build->Emit(OP_LKF, regNum, emitval.RegNum);
|
||||
build->Emit(OP_SDP, arrOffsetReg, regNum, zero);
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
build->Emit(OP_LKP, regNum, build->GetConstantAddress(constval->GetValue().GetPointer()));
|
||||
build->Emit(OP_SP_R, build->FramePointer.RegNum, regNum, arrOffsetReg);
|
||||
build->Emit(OP_LKP, regNum, emitval.RegNum);
|
||||
build->Emit(OP_SP, arrOffsetReg, regNum, zero);
|
||||
break;
|
||||
|
||||
case REGT_STRING:
|
||||
build->Emit(OP_LKS, regNum, build->GetConstantString(constval->GetValue().GetString()));
|
||||
build->Emit(OP_SS_R, build->FramePointer.RegNum, regNum, arrOffsetReg);
|
||||
build->Emit(OP_LKS, regNum, emitval.RegNum);
|
||||
build->Emit(OP_SS, arrOffsetReg, regNum, zero);
|
||||
break;
|
||||
}
|
||||
build->Registers[regtype].Return(regNum, 1);
|
||||
|
||||
emitval.Free(build);
|
||||
build->Registers[regtype].Return(regNum, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (regtype)
|
||||
{
|
||||
default:
|
||||
case REGT_INT:
|
||||
build->Emit(OP_SW_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg);
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
build->Emit(OP_SDP_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg);
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
build->Emit(OP_SP_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg);
|
||||
break;
|
||||
|
||||
case REGT_STRING:
|
||||
build->Emit(OP_SS_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg);
|
||||
break;
|
||||
}
|
||||
emitval.Free(build);
|
||||
build->Emit(v->ValueType->GetStoreOp(), arrOffsetReg, emitval.RegNum, zero);
|
||||
}
|
||||
emitval.Free(build);
|
||||
|
||||
build->Emit(OP_ADD_RK, arrOffsetReg, arrOffsetReg, elementSizeConst);
|
||||
if (!isDynamicArray)
|
||||
{
|
||||
build->Emit(OP_ADDA_RK, arrOffsetReg, arrOffsetReg, elementSizeConst);
|
||||
}
|
||||
}
|
||||
if (!isDynamicArray)
|
||||
{
|
||||
build->Registers[REGT_POINTER].Return(arrOffsetReg, 1);
|
||||
}
|
||||
build->Registers[REGT_INT].Return(arrOffsetReg, 1);
|
||||
|
||||
return ExpEmit();
|
||||
}
|
||||
|
|
|
@ -175,7 +175,7 @@ static int fieldcmp(const void * a, const void * b)
|
|||
|
||||
void InitImports()
|
||||
{
|
||||
auto fontstruct = NewStruct("FFont", nullptr, true);
|
||||
auto fontstruct = NewStruct("Font", nullptr, true);
|
||||
fontstruct->Size = sizeof(FFont);
|
||||
fontstruct->Align = alignof(FFont);
|
||||
NewPointer(fontstruct, false)->InstallHandlers(
|
||||
|
|
|
@ -272,4 +272,3 @@ struct AFuncDesc;
|
|||
struct FieldDesc;
|
||||
AFuncDesc *FindFunction(PContainerType *cls, const char * string);
|
||||
FieldDesc *FindField(PContainerType *cls, const char * string);
|
||||
//void SetImplicitArgs(TArray<PType*>* args, TArray<uint32_t>* argflags, TArray<FName>* argnames, PContainerType* cls, uint32_t funcflags, int useflags);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "v_video.h"
|
||||
|
||||
|
||||
CVAR(Bool, gl_customshader, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL);
|
||||
CVAR(Bool, gl_customshader, true, 0);
|
||||
|
||||
|
||||
static IHardwareTexture* (*layercallback)(int layer, int translation);
|
||||
|
|
|
@ -320,6 +320,8 @@ public:
|
|||
void NeedUpdate() { bNeedsUpdate = true; }
|
||||
void SetUpdated(bool rendertype) { bNeedsUpdate = false; bFirstUpdate = false; bLastUpdateType = rendertype; }
|
||||
|
||||
void SetAspectRatio(double aspectScale, bool useTextureRatio) { aspectRatio = (float)aspectScale * (useTextureRatio? ((float)Width / Height) : 1); }
|
||||
|
||||
protected:
|
||||
|
||||
bool bLastUpdateType = false;
|
||||
|
|
|
@ -987,6 +987,8 @@ int SmackerDecoder::DecodeAudio(uint32_t size, SmackerAudioTrack &track)
|
|||
return -1;
|
||||
}
|
||||
|
||||
memset(h, 0, sizeof(HuffContext) * 4);
|
||||
|
||||
// Initialize
|
||||
for (i = 0; i < (1 << (sampleBits + stereo)); i++) {
|
||||
h[i].length = 256;
|
||||
|
@ -1142,7 +1144,7 @@ uint32_t SmackerDecoder::GetAudioData(uint32_t trackIndex, int16_t *audioBuffer)
|
|||
SmackerAudioTrack *track = &audioTracks[trackIndex];
|
||||
|
||||
if (track->bytesReadThisFrame) {
|
||||
memcpy(audioBuffer, track->buffer, min(track->bufferSize, track->bytesReadThisFrame));
|
||||
memcpy(audioBuffer, track->buffer, std::min(track->bufferSize, track->bytesReadThisFrame));
|
||||
}
|
||||
|
||||
return track->bytesReadThisFrame;
|
||||
|
|
4
source/common/thirdparty/math/cmath.h
vendored
4
source/common/thirdparty/math/cmath.h
vendored
|
@ -56,12 +56,12 @@ extern FFastTrig fasttrig;
|
|||
|
||||
inline double fastcosbam(double v)
|
||||
{
|
||||
return fasttrig.cos(v);
|
||||
return fasttrig.cos(xs_CRoundToUInt(v));
|
||||
}
|
||||
|
||||
inline double fastsinbam(double v)
|
||||
{
|
||||
return fasttrig.sin(v);
|
||||
return fasttrig.sin(xs_CRoundToUInt(v));
|
||||
}
|
||||
|
||||
inline double fastcosdeg(double v)
|
||||
|
|
|
@ -44,3 +44,8 @@ double I_GetInputFrac(bool const synchronised, double const ticrate = GameTicRat
|
|||
|
||||
// Reset the last input check to after a lengthy operation
|
||||
void I_ResetInputTime();
|
||||
|
||||
// Pause a bit.
|
||||
// [RH] Despite the name, it apparently never waited for the VBL, even in
|
||||
// the original DOS version (if the Heretic/Hexen source is any indicator).
|
||||
void I_WaitVBL(int count);
|
||||
|
|
Loading…
Reference in a new issue