- Backend update from Raze

This commit is contained in:
Christoph Oelckers 2021-04-19 12:58:35 +02:00
commit ba146ed5e5
43 changed files with 473 additions and 168 deletions

View file

@ -80,6 +80,8 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
mVertexBuffer = screen->CreateVertexBuffer();
mIndexBuffer = screen->CreateIndexBuffer();
int data[4] = {};
mIndexBuffer->SetData(4, data); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes.
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
mVertexBuffer->SetData(bytesize, nullptr, false);

View file

@ -9,7 +9,6 @@
class FRenderState;
struct secplane_t;
struct subsector_t;
struct FFlatVertex
{

View file

@ -4,8 +4,6 @@
#include "tarray.h"
#include "vectors.h"
struct FLevelLocals;
namespace hwrenderer
{

View file

@ -200,9 +200,8 @@ struct StreamData
FVector4 uSplitBottomPlane;
FVector4 uDetailParms;
#ifdef NPOT_EMULATION
FVector2 uNpotEmulation;
#endif
FVector4 uNpotEmulation;
FVector4 padding1, padding2, padding3;
};
class FRenderState
@ -295,7 +294,7 @@ public:
mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f };
#ifdef NPOT_EMULATION
mStreamData.uNpotEmulation = { 0,0 };
mStreamData.uNpotEmulation = { 0,0,0,0 };
#endif
mModelMatrix.loadIdentity();
mTextureMatrix.loadIdentity();
@ -490,7 +489,7 @@ public:
void SetNpotEmulation(float factor, float offset)
{
#ifdef NPOT_EMULATION
mStreamData.uNpotEmulation = { offset, factor };
mStreamData.uNpotEmulation = { offset, factor, 0, 0 };
#endif
}

View file

@ -62,13 +62,7 @@
#include "hw_renderstate.h"
#include "v_video.h"
#include "hwrenderer/data/buffers.h"
// 57 world units roughly represent one sky texel for the glTranslate call.
enum
{
skyoffsetfactor = 57
};
#include "version.h"
//-----------------------------------------------------------------------------
//
@ -150,7 +144,7 @@ FSkyVertexBuffer::~FSkyVertexBuffer()
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip)
{
static const FAngle maxSideAngle = 60.f;
static const float scale = 10000.;
@ -187,6 +181,37 @@ void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
mVertices.Push(vert);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip)
{
static const FAngle maxSideAngle = 60.f;
static const float scale = 10000.;
FAngle topAngle = (c / (float)mColumns * 360.f);
FVector2 pos = topAngle.ToVector(scale);
float z = (!zflip) ? (mRows - r) * 4000.f : -(mRows - r) * 4000.f;
FSkyVertex vert;
vert.color = r == 0 ? 0xffffff : 0xffffffff;
// And the texture coordinates.
if (zflip) r = mRows * 2 - r;
vert.u = 0.5f + (-c / (float)mColumns);
vert.v = (r / (float)(2*mRows));
// And finally the vertex.
vert.x = pos.X;
vert.y = z - 1.f;
vert.z = pos.Y;
mVertices.Push(vert);
}
//-----------------------------------------------------------------------------
//
@ -194,27 +219,58 @@ void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::CreateSkyHemisphere(int hemi)
void FSkyVertexBuffer::CreateSkyHemisphereDoom(int hemi)
{
int r, c;
bool zflip = !!(hemi & SKYHEMI_LOWER);
mPrimStart.Push(mVertices.Size());
mPrimStartDoom.Push(mVertices.Size());
for (c = 0; c < mColumns; c++)
{
SkyVertex(1, c, zflip);
SkyVertexDoom(1, c, zflip);
}
// The total number of triangles per hemisphere can be calculated
// as follows: rows * columns * 2 + 2 (for the top cap).
for (r = 0; r < mRows; r++)
{
mPrimStart.Push(mVertices.Size());
mPrimStartDoom.Push(mVertices.Size());
for (c = 0; c <= mColumns; c++)
{
SkyVertex(r + zflip, c, zflip);
SkyVertex(r + 1 - zflip, c, zflip);
SkyVertexDoom(r + zflip, c, zflip);
SkyVertexDoom(r + 1 - zflip, c, zflip);
}
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::CreateSkyHemisphereBuild(int hemi)
{
int r, c;
bool zflip = !!(hemi & SKYHEMI_LOWER);
mPrimStartBuild.Push(mVertices.Size());
for (c = 0; c < mColumns; c++)
{
SkyVertexBuild(1, c, zflip);
}
// The total number of triangles per hemisphere can be calculated
// as follows: rows * columns * 2 + 2 (for the top cap).
for (r = 0; r < mRows; r++)
{
mPrimStartBuild.Push(mVertices.Size());
for (c = 0; c <= mColumns; c++)
{
SkyVertexBuild(r + zflip, c, zflip);
SkyVertexBuild(r + 1 - zflip, c, zflip);
}
}
}
@ -248,9 +304,13 @@ void FSkyVertexBuffer::CreateDome()
mColumns = 128;
mRows = 4;
CreateSkyHemisphere(SKYHEMI_UPPER);
CreateSkyHemisphere(SKYHEMI_LOWER);
mPrimStart.Push(mVertices.Size());
CreateSkyHemisphereDoom(SKYHEMI_UPPER);
CreateSkyHemisphereDoom(SKYHEMI_LOWER);
mPrimStartDoom.Push(mVertices.Size());
CreateSkyHemisphereBuild(SKYHEMI_UPPER);
CreateSkyHemisphereBuild(SKYHEMI_LOWER);
mPrimStartBuild.Push(mVertices.Size());
mSideStart = mVertices.Size();
mFaceStart[0] = mSideStart + 10;
@ -324,7 +384,7 @@ void FSkyVertexBuffer::CreateDome()
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelMatrix, VSMatrix &textureMatrix, bool tiled)
void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelMatrix, VSMatrix &textureMatrix, bool tiled, float xscale, float yscale)
{
float texw = tex->GetDisplayWidth();
float texh = tex->GetDisplayHeight();
@ -332,37 +392,46 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_
modelMatrix.loadIdentity();
modelMatrix.rotate(-180.0f + x_offset, 0.f, 1.f, 0.f);
float xscale = texw < 1024.f ? floorf(1024.f / float(texw)) : 1.f;
float yscale = 1.f;
if (xscale == 0) xscale = texw < 1024.f ? floorf(1024.f / float(texw)) : 1.f;
auto texskyoffset = tex->GetSkyOffset() + skyoffset;
if (texh <= 128 && tiled)
if (yscale == 0)
{
modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f);
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
yscale = 240.f / texh;
}
else if (texh < 128)
{
// smaller sky textures must be tiled. We restrict it to 128 sky pixels, though
modelMatrix.translate(0.f, -1250.f, 0.f);
modelMatrix.scale(1.f, 128 / 230.f, 1.f);
yscale = float(128 / texh); // intentionally left as integer.
}
else if (texh < 200)
{
modelMatrix.translate(0.f, -1250.f, 0.f);
modelMatrix.scale(1.f, texh / 230.f, 1.f);
}
else if (texh <= 240)
{
modelMatrix.translate(0.f, (200 - texh + texskyoffset)*skyoffsetfactor, 0.f);
modelMatrix.scale(1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f, 1.f);
if (texh <= 128 && tiled)
{
modelMatrix.translate(0.f, (-40 + texskyoffset) * skyoffsetfactor, 0.f);
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
yscale = 240.f / texh;
}
else if (texh < 128)
{
// smaller sky textures must be tiled. We restrict it to 128 sky pixels, though
modelMatrix.translate(0.f, -1250.f, 0.f);
modelMatrix.scale(1.f, 128 / 230.f, 1.f);
yscale = float(128 / texh); // intentionally left as integer.
}
else if (texh < 200)
{
modelMatrix.translate(0.f, -1250.f, 0.f);
modelMatrix.scale(1.f, texh / 230.f, 1.f);
yscale = 1.f;
}
else if (texh <= 240)
{
modelMatrix.translate(0.f, (200 - texh + texskyoffset) * skyoffsetfactor, 0.f);
modelMatrix.scale(1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f, 1.f);
yscale = 1.f;
}
else
{
modelMatrix.translate(0.f, (-40 + texskyoffset) * skyoffsetfactor, 0.f);
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
yscale = 240.f / texh;
}
}
else
{
modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f);
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
yscale = 240.f / texh;
modelMatrix.translate(0.f, (-40 + texskyoffset) * skyoffsetfactor, 0.f);
modelMatrix.scale(1.f, 0.8f * 1.17f, 1.f);
}
textureMatrix.loadIdentity();
textureMatrix.scale(mirror ? -xscale : xscale, yscale, 1.f);
@ -375,7 +444,7 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, bool apply)
void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, TArray<unsigned int>& mPrimStart, bool apply)
{
state.Draw(prim, mPrimStart[row], mPrimStart[row + 1] - mPrimStart[row]);
}
@ -386,36 +455,35 @@ void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, b
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled)
void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which)
{
if (tex)
auto& primStart = which ? mPrimStartBuild : mPrimStartDoom;
if (tex && tex->isValid())
{
state.SetMaterial(tex, UF_Texture, 0, CLAMP_NONE, 0, -1);
state.EnableModelMatrix(true);
state.EnableTextureMatrix(true);
SetupMatrices(tex, x_offset, y_offset, mirror, mode, state.mModelMatrix, state.mTextureMatrix, tiled);
}
int rc = mRows + 1;
// The caps only get drawn for the main layer but not for the overlay.
if (mode == FSkyVertexBuffer::SKYMODE_MAINLAYER && tex != NULL)
if (mode == FSkyVertexBuffer::SKYMODE_MAINLAYER && tex != nullptr)
{
auto& col = R_GetSkyCapColor(tex);
state.SetObjectColor(col.first);
state.EnableTexture(false);
RenderRow(state, DT_TriangleFan, 0);
RenderRow(state, DT_TriangleFan, 0, primStart);
state.SetObjectColor(col.second);
RenderRow(state, DT_TriangleFan, rc);
RenderRow(state, DT_TriangleFan, rc, primStart);
state.EnableTexture(true);
}
state.SetObjectColor(0xffffffff);
for (int i = 1; i <= mRows; i++)
{
RenderRow(state, DT_TriangleStrip, i, i == 1);
RenderRow(state, DT_TriangleStrip, rc + i, false);
RenderRow(state, DT_TriangleStrip, i, primStart, i == 1);
RenderRow(state, DT_TriangleStrip, rc + i, primStart, false);
}
state.EnableTextureMatrix(false);
@ -423,13 +491,29 @@ void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float
}
//-----------------------------------------------------------------------------
//
// This is only for Doom-style skies.
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale, float yscale)
{
if (tex)
{
SetupMatrices(tex, x_offset, y_offset, mirror, mode, state.mModelMatrix, state.mTextureMatrix, tiled, xscale, yscale);
}
RenderDome(state, tex, mode, false);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::RenderBox(FRenderState& state, FTextureID texno, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2)
void FSkyVertexBuffer::RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2)
{
int faces;

View file

@ -11,6 +11,12 @@ class IVertexBuffer;
struct HWSkyPortal;
struct HWDrawInfo;
// 57 world units roughly represent one sky texel for the glTranslate call.
enum
{
skyoffsetfactor = 57
};
struct FSkyVertex
{
float x, y, z, u, v;
@ -55,7 +61,8 @@ public:
IVertexBuffer *mVertexBuffer;
TArray<FSkyVertex> mVertices;
TArray<unsigned int> mPrimStart;
TArray<unsigned int> mPrimStartDoom;
TArray<unsigned int> mPrimStartBuild;
int mRows, mColumns;
@ -63,15 +70,17 @@ public:
int mFaceStart[7];
int mSideStart;
void SkyVertex(int r, int c, bool yflip);
void CreateSkyHemisphere(int hemi);
void SkyVertexDoom(int r, int c, bool yflip);
void SkyVertexBuild(int r, int c, bool yflip);
void CreateSkyHemisphereDoom(int hemi);
void CreateSkyHemisphereBuild(int hemi);
void CreateDome();
public:
FSkyVertexBuffer();
~FSkyVertexBuffer();
void SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelmatrix, VSMatrix &textureMatrix, bool tiled);
void SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelmatrix, VSMatrix &textureMatrix, bool tiled, float xscale = 0, float vertscale = 0);
std::pair<IVertexBuffer *, IIndexBuffer *> GetBufferObjects() const
{
return std::make_pair(mVertexBuffer, nullptr);
@ -83,8 +92,9 @@ public:
else return mSideStart;
}
void RenderRow(FRenderState& state, EDrawType prim, int row, bool apply = true);
void RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled);
void RenderBox(FRenderState& state, FTextureID texno, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2);
void RenderRow(FRenderState& state, EDrawType prim, int row, TArray<unsigned int>& mPrimStart, bool apply = true);
void RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which);
void RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale = 0, float yscale = 0);
void RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2);
};

View file

@ -85,7 +85,6 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
vb.UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size());
state.SetVertexBuffer(&vb);
state.EnableFog(false);
state.SetScreenFade(drawer->screenFade);
for(auto &cmd : commands)
{
@ -94,6 +93,7 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
state.SetRenderStyle(cmd.mRenderStyle);
state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
state.EnableFog(2); // Special 2D mode 'fog'.
state.SetScreenFade(cmd.mScreenFade);
state.SetTextureMode(cmd.mDrawMode);

View file

@ -45,7 +45,6 @@
#include "hw_shadowmap.h"
struct sector_t;
struct FPortalSceneState;
class FSkyVertexBuffer;
class IIndexBuffer;
@ -147,7 +146,7 @@ public:
IntRect mScreenViewport;
IntRect mSceneViewport;
IntRect mOutputLetterbox;
float mSceneClearColor[4];
float mSceneClearColor[4]{ 0,0,0,255 };
public:
DFrameBuffer (int width=1, int height=1);

View file

@ -163,9 +163,8 @@ static const char *shaderBindings = R"(
vec4 uSplitBottomPlane;
vec4 uDetailParms;
#ifdef NPOT_EMULATION
vec2 uNpotEmulation;
#endif
vec4 uNpotEmulation;
vec4 padding1, padding2, padding3;
};
layout(set = 0, binding = 3, std140) uniform StreamUBO {
@ -297,6 +296,9 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
code << defines;
code << "\n$placeholder$"; // here the code can later add more needed #defines.
code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n";
#ifdef NPOT_EMULATION
code << "#define NPOT_EMULATION\n";
#endif
code << shaderBindings;
FString placeholder = "\n";

View file

@ -390,7 +390,7 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels)
{
return new VkHardwareTexture();
return new VkHardwareTexture(numchannels);
}
FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags)

View file

@ -37,8 +37,9 @@
VkHardwareTexture *VkHardwareTexture::First = nullptr;
VkHardwareTexture::VkHardwareTexture()
VkHardwareTexture::VkHardwareTexture(int numchannels)
{
mTexelsize = numchannels;
Next = First;
First = this;
if (Next) Next->Prev = this;
@ -126,7 +127,8 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
if (!tex->isHardwareCanvas())
{
FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData);
CreateTexture(texbuffer.mWidth, texbuffer.mHeight, 4, VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer);
bool indexed = flags & CTF_Indexed;
CreateTexture(texbuffer.mWidth, texbuffer.mHeight,indexed? 1 : 4, indexed? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer, !indexed);
}
else
{
@ -156,7 +158,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
}
}
void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels)
void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap)
{
if (w <= 0 || h <= 0)
throw CVulkanError("Trying to create zero size texture");
@ -177,7 +179,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
ImageBuilder imgbuilder;
imgbuilder.setFormat(format);
imgbuilder.setSize(w, h, GetMipLevels(w, h));
imgbuilder.setSize(w, h, !mipmap ? 1 : GetMipLevels(w, h));
imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
mImage.Image = imgbuilder.create(fb->device);
mImage.Image->SetDebugName("VkHardwareTexture.mImage");
@ -203,7 +205,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
fb->FrameDeleteList.Buffers.push_back(std::move(stagingBuffer));
mImage.GenerateMipmaps(cmdbuffer);
if (mipmap) mImage.GenerateMipmaps(cmdbuffer);
}
int VkHardwareTexture::GetMipLevels(int w, int h)
@ -268,6 +270,7 @@ uint8_t *VkHardwareTexture::MapBuffer()
unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name)
{
CreateTexture(w, h, mTexelsize, mTexelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM, buffer, mipmap);
return 0;
}
@ -371,10 +374,6 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
int clampmode = state.mClampMode;
int translation = state.mTranslation;
auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation);
if (remap)
translation = remap->Index;
clampmode = base->GetClampMode(clampmode);
for (auto& set : mDescriptorSets)
@ -395,10 +394,23 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
MaterialLayerInfo *layer;
auto systex = static_cast<VkHardwareTexture*>(GetLayer(0, state.mTranslation, &layer));
update.addCombinedImageSampler(descriptor.get(), 0, systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
for (int i = 1; i < numLayers; i++)
if (!(layer->scaleFlags & CTF_Indexed))
{
auto systex = static_cast<VkHardwareTexture*>(GetLayer(i, 0, &layer));
update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
for (int i = 1; i < numLayers; i++)
{
auto systex = static_cast<VkHardwareTexture*>(GetLayer(i, 0, &layer));
update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
}
}
else
{
for (int i = 1; i < 3; i++)
{
auto systex = static_cast<VkHardwareTexture*>(GetLayer(i, translation, &layer));
update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
}
numLayers = 3;
}
auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView();

View file

@ -24,7 +24,7 @@ class VkHardwareTexture : public IHardwareTexture
{
friend class VkMaterial;
public:
VkHardwareTexture();
VkHardwareTexture(int numchannels);
~VkHardwareTexture();
static void ResetAll();
@ -45,7 +45,7 @@ public:
private:
void CreateImage(FTexture *tex, int translation, int flags);
void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels);
void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap);
static int GetMipLevels(int w, int h);
static VkHardwareTexture *First;