diff --git a/src/common/textures/animtexture.cpp b/src/common/textures/animtexture.cpp index 4dbf2d111..b09c5cd18 100644 --- a/src/common/textures/animtexture.cpp +++ b/src/common/textures/animtexture.cpp @@ -50,7 +50,7 @@ void AnimTexture::SetFrame(const uint8_t *palette, const void *data_) { memcpy(Palette, palette, 768); memcpy(Image.Data(), data_, Width * Height); - SystemTextures.Clean(true, true); + CleanHardwareTextures(true, true); } //=========================================================================== diff --git a/src/common/textures/hw_ihwtexture.h b/src/common/textures/hw_ihwtexture.h index 24b92c926..73023014c 100644 --- a/src/common/textures/hw_ihwtexture.h +++ b/src/common/textures/hw_ihwtexture.h @@ -14,8 +14,8 @@ public: MAX_TEXTURES = 16 }; - IHardwareTexture() {} - virtual ~IHardwareTexture() {} + IHardwareTexture() = default; + virtual ~IHardwareTexture() = default; virtual void DeleteDescriptors() { } diff --git a/src/common/textures/hw_material.cpp b/src/common/textures/hw_material.cpp index 8c0bc06ef..bb39cef7b 100644 --- a/src/common/textures/hw_material.cpp +++ b/src/common/textures/hw_material.cpp @@ -30,6 +30,21 @@ IHardwareTexture* CreateHardwareTexture(); +// We really do not need to create more than one hardware texture per image source. +// However, the internal handling depends on FTexture for everything so this array maps each all textures sharing the same master texture that gets used in the layer array. +static TMap imageToMasterTexture; + +static FTexture* GetMasterTexture(FTexture* tx) +{ + if (tx->GetUseType() == ETextureType::Null) return tx; // Null textures never get redirected + auto img = tx->GetImage(); + if (!img) return tx; // this is not an image texture and represents itself. + auto find = imageToMasterTexture.CheckKey(img); + if (find) return *find; // already got a master texture for this. Return it. + imageToMasterTexture.Insert(img, tx); + return tx; // this is a newly added master texture. +} + //=========================================================================== // // Constructor @@ -39,7 +54,8 @@ IHardwareTexture* CreateHardwareTexture(); FMaterial::FMaterial(FTexture * tx, bool expanded) { mShaderIndex = SHADER_Default; - sourcetex = tex = tx; + sourcetex = tx; + imgtex = GetMasterTexture(tx); if (tx->UseType == ETextureType::SWCanvas && static_cast(tx)->GetColorFormat() == 0) { @@ -63,7 +79,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) { for (auto &texture : { tx->Normal, tx->Specular }) { - mTextureLayers.Push(texture); + mTextureLayers.Push(GetMasterTexture(texture)); } mShaderIndex = SHADER_Specular; } @@ -71,7 +87,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) { for (auto &texture : { tx->Normal, tx->Metallic, tx->Roughness, tx->AmbientOcclusion }) { - mTextureLayers.Push(texture); + mTextureLayers.Push(GetMasterTexture(texture)); } mShaderIndex = SHADER_PBR; } @@ -80,7 +96,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) tx->CreateDefaultBrightmap(); if (tx->Brightmap) { - mTextureLayers.Push(tx->Brightmap); + mTextureLayers.Push(GetMasterTexture(tx->Brightmap)); mLayerFlags |= TEXF_Brightmap; } else @@ -89,7 +105,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) } if (tx->Detailmap) { - mTextureLayers.Push(tx->Detailmap); + mTextureLayers.Push(GetMasterTexture(tx->Detailmap)); mLayerFlags |= TEXF_Detailmap; } else @@ -98,7 +114,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) } if (tx->Glowmap) { - mTextureLayers.Push(tx->Glowmap); + mTextureLayers.Push(GetMasterTexture(tx->Glowmap)); mLayerFlags |= TEXF_Glowmap; } else @@ -114,7 +130,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) for (auto &texture : tx->CustomShaderTextures) { if (texture == nullptr) continue; - mTextureLayers.Push(texture); + mTextureLayers.Push(GetMasterTexture(texture)); } mShaderIndex = tx->shaderindex; } @@ -167,11 +183,11 @@ FMaterial::~FMaterial() void FMaterial::SetSpriteRect() { - auto leftOffset = tex->GetLeftOffsetHW(); - auto topOffset = tex->GetTopOffsetHW(); + auto leftOffset = sourcetex->GetLeftOffsetHW(); + auto topOffset = sourcetex->GetTopOffsetHW(); - float fxScale = (float)tex->Scale.X; - float fyScale = (float)tex->Scale.Y; + float fxScale = (float)sourcetex->Scale.X; + float fyScale = (float)sourcetex->Scale.Y; // mSpriteRect is for positioning the sprite in the scene. mSpriteRect.left = -leftOffset / fxScale; @@ -311,7 +327,7 @@ outl: IHardwareTexture *FMaterial::GetLayer(int i, int translation, FTexture **pLayer) { - FTexture *layer = i == 0 ? tex : mTextureLayers[i - 1]; + FTexture *layer = i == 0 ? imgtex : mTextureLayers[i - 1]; if (pLayer) *pLayer = layer; if (layer && layer->UseType!=ETextureType::Null) diff --git a/src/common/textures/hw_material.h b/src/common/textures/hw_material.h index 026557376..11cbc58b4 100644 --- a/src/common/textures/hw_material.h +++ b/src/common/textures/hw_material.h @@ -28,6 +28,7 @@ enum class FMaterial { + private: TArray mTextureLayers; int mShaderIndex; int mLayerFlags = 0; @@ -48,14 +49,37 @@ class FMaterial bool TrimBorders(uint16_t *rect); public: - FTexture *tex; - FTexture *sourcetex; // in case of redirection this is different from tex. - + FTexture *sourcetex; // the owning texture. + FTexture* imgtex; // the master texture for the backing image. Can be different from sourcetex and should not be in the layer array because that'd confuse the precacher. + FMaterial(FTexture *tex, bool forceexpand); ~FMaterial(); int GetLayerFlags() const { return mLayerFlags; } void SetSpriteRect(); int GetShaderIndex() const { return mShaderIndex; } + + FTexture* Source() const + { + return sourcetex; + } + FTexture* BaseLayer() const + { + // Only for spftpoly! + return imgtex; + } + bool isFullbright() const + { + return sourcetex->isFullbright(); + } + bool isHardwareCanvas() const + { + return sourcetex->isHardwareCanvas(); + } + bool GetTranslucency() + { + // This queries the master texture to reduce recalculations. + return imgtex->GetTranslucency(); + } void AddTextureLayer(FTexture *tex) { ValidateTexture(tex, false); @@ -77,7 +101,7 @@ public: bool hasCanvas() { - return tex->isHardwareCanvas(); + return sourcetex->isHardwareCanvas(); } IHardwareTexture *GetLayer(int i, int translation, FTexture **pLayer = nullptr); diff --git a/src/common/textures/texture.cpp b/src/common/textures/texture.cpp index cdaa29d55..a2f02e3eb 100644 --- a/src/common/textures/texture.cpp +++ b/src/common/textures/texture.cpp @@ -733,6 +733,12 @@ bool FTexture::DetermineTranslucency() return !!bTranslucent; } + +void FTexture::CleanHardwareTextures(bool cleannormal, bool cleanexpanded) +{ + SystemTextures.Clean(cleannormal, cleanexpanded); +} + //=========================================================================== // // the default just returns an empty texture. diff --git a/src/common/textures/texturemanager.cpp b/src/common/textures/texturemanager.cpp index 76024b4ec..4e87a893e 100644 --- a/src/common/textures/texturemanager.cpp +++ b/src/common/textures/texturemanager.cpp @@ -119,7 +119,7 @@ void FTextureManager::FlushAll() { for (int j = 0; j < 2; j++) { - Textures[i].Texture->SystemTextures.Clean(true, true); + Textures[i].Texture->CleanHardwareTextures(true, true); DeleteSoftwareTexture(Textures[i].Texture->SoftwareTexture); Textures[i].Texture->SoftwareTexture = nullptr; } diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index cefb39114..35487c772 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -248,6 +248,7 @@ public: virtual FImageSource *GetImage() const { return nullptr; } void AddAutoMaterials(); void CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha, bool checkonly); + void CleanHardwareTextures(bool cleannormal, bool cleanextended); // These are mainly meant for 2D code which only needs logical information about the texture to position it properly. int GetDisplayWidth() { int foo = int((Width * 2) / Scale.X); return (foo >> 1) + (foo & 1); } diff --git a/src/rendering/2d/f_wipe.cpp b/src/rendering/2d/f_wipe.cpp index 6b66b7dd6..f25577491 100644 --- a/src/rendering/2d/f_wipe.cpp +++ b/src/rendering/2d/f_wipe.cpp @@ -373,8 +373,8 @@ bool Wiper_Burn::Run(int ticks) done = (Density < 0); } - BurnTexture->SystemTextures.Clean(true, true); - endScreen->SystemTextures.Clean(false, false); + BurnTexture->CleanHardwareTextures(true, true); + endScreen->CleanHardwareTextures(false, false); const uint8_t *src = BurnArray; uint32_t *dest = (uint32_t *)BurnTexture->GetBuffer(); diff --git a/src/rendering/gl/renderer/gl_renderstate.cpp b/src/rendering/gl/renderer/gl_renderstate.cpp index 4eb25647b..8da456248 100644 --- a/src/rendering/gl/renderer/gl_renderstate.cpp +++ b/src/rendering/gl/renderer/gl_renderstate.cpp @@ -298,7 +298,7 @@ void FGLRenderState::Apply() void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader) { - if (mat->tex->isHardwareCanvas()) + if (mat->isHardwareCanvas()) { mTempTM = TM_OPAQUE; } @@ -306,11 +306,11 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio { mTempTM = TM_NORMAL; } + auto tex = mat->Source(); mEffectState = overrideshader >= 0 ? overrideshader : mat->GetShaderIndex(); - mShaderTimer = mat->tex->shaderspeed; - SetSpecular(mat->tex->Glossiness, mat->tex->SpecularLevel); + mShaderTimer = tex->shaderspeed; + SetSpecular(tex->Glossiness, tex->SpecularLevel); - auto tex = mat->tex; if (tex->UseType == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER; if (tex->isHardwareCanvas()) clampmode = CLAMP_CAMTEX; else if ((tex->isWarped() || tex->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; diff --git a/src/rendering/gl/system/gl_framebuffer.cpp b/src/rendering/gl/system/gl_framebuffer.cpp index f025a4e86..4b9011835 100644 --- a/src/rendering/gl/system/gl_framebuffer.cpp +++ b/src/rendering/gl/system/gl_framebuffer.cpp @@ -308,18 +308,17 @@ IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture() void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) { - auto tex = mat->tex; - if (tex->isSWCanvas()) return; + if (mat->Source()->isSWCanvas()) return; int flags = mat->isExpanded() ? CTF_Expand : 0; int numLayers = mat->GetLayers(); - auto base = static_cast(mat->GetLayer(0, translation)); + FTexture* layer; + auto base = static_cast(mat->GetLayer(0, translation, &layer)); - if (base->BindOrCreate(tex, 0, CLAMP_NONE, translation, flags)) + if (base->BindOrCreate(layer, 0, CLAMP_NONE, translation, flags)) { for (int i = 1; i < numLayers; i++) { - FTexture *layer; auto systex = static_cast(mat->GetLayer(i, 0, &layer)); systex->BindOrCreate(layer, i, CLAMP_NONE, 0, mat->isExpanded() ? CTF_Expand : 0); } diff --git a/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp b/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp index eb81a3170..851c2e148 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp @@ -101,7 +101,7 @@ void HWDrawInfo::AddFlat(HWFlat *flat, bool fog) // translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list. list = (flat->renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER; } - else if (flat->gltexture->tex->GetTranslucency()) + else if (flat->gltexture->GetTranslucency()) { if (flat->stack) { diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index 204a1e530..9f592bf05 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -349,7 +349,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) } else { - if (!gltexture->tex->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + if (!gltexture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); else state.AlphaFunc(Alpha_GEqual, 0.f); state.SetMaterial(gltexture, CLAMP_NONE, 0, -1); state.SetPlaneTextureRotation(&plane, gltexture); @@ -407,7 +407,7 @@ void HWFlat::Process(HWDrawInfo *di, sector_t * model, int whichplane, bool fog) { gltexture=FMaterial::ValidateTexture(plane.texture, false, true); if (!gltexture) return; - if (gltexture->tex->isFullbright()) + if (gltexture->isFullbright()) { Colormap.MakeWhite(); lightlevel=255; diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index d68a9fa3a..f9953051d 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -960,7 +960,7 @@ void HWHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state) di->SetCameraPos(vp.Pos); - if (gltexture && gltexture->tex->isFullbright()) + if (gltexture && gltexture->isFullbright()) { // glowing textures are always drawn full bright without color di->SetColor(state, 255, 0, false, origin->colormap, 1.f); diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 6bdb8f842..146102828 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -61,8 +61,9 @@ void HWSkyInfo::init(HWDrawInfo *di, int sky1, PalEntry FadeColor) } FTextureID texno = s->GetTexture(pos); - texture[0] = FMaterial::ValidateTexture(texno, false, true); - if (!texture[0] || !texture[0]->tex->isValid()) goto normalsky; + FTexture* tex = TexMan.GetTexture(texno, true); + if (!tex || !tex->isValid()) goto normalsky; + texture[0] = FMaterial::ValidateTexture(tex, false); skytexno1 = texno; x_offset[0] = s->GetTextureXOffset(pos) * (360.f/65536.f); y_offset = s->GetTextureYOffset(pos); diff --git a/src/rendering/hwrenderer/scene/hw_skydome.cpp b/src/rendering/hwrenderer/scene/hw_skydome.cpp index 9b7942383..968b79fbb 100644 --- a/src/rendering/hwrenderer/scene/hw_skydome.cpp +++ b/src/rendering/hwrenderer/scene/hw_skydome.cpp @@ -292,9 +292,10 @@ void FSkyVertexBuffer::SetupMatrices(HWDrawInfo *di, FMaterial *tex, float x_off float xscale = texw < 1024.f ? floor(1024.f / float(texw)) : 1.f; float yscale = 1.f; + auto texskyoffset = tex->Source()->GetSkyOffset() + skyoffset; if (texh <= 128 && (di->Level->flags & LEVEL_FORCETILEDSKY)) { - modelMatrix.translate(0.f, (-40 + tex->tex->GetSkyOffset() + skyoffset)*skyoffsetfactor, 0.f); + modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f); modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f); yscale = 240.f / texh; } @@ -312,12 +313,12 @@ void FSkyVertexBuffer::SetupMatrices(HWDrawInfo *di, FMaterial *tex, float x_off } else if (texh <= 240) { - modelMatrix.translate(0.f, (200 - texh + tex->tex->GetSkyOffset() + skyoffset)*skyoffsetfactor, 0.f); + 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); } else { - modelMatrix.translate(0.f, (-40 + tex->tex->GetSkyOffset() + skyoffset)*skyoffsetfactor, 0.f); + modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f); modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f); yscale = 240.f / texh; } diff --git a/src/rendering/hwrenderer/scene/hw_skyportal.cpp b/src/rendering/hwrenderer/scene/hw_skyportal.cpp index 98811286e..d4c4f11a7 100644 --- a/src/rendering/hwrenderer/scene/hw_skyportal.cpp +++ b/src/rendering/hwrenderer/scene/hw_skyportal.cpp @@ -66,12 +66,13 @@ void HWSkyPortal::RenderDome(HWDrawInfo *di, FRenderState &state, FMaterial * te // The caps only get drawn for the main layer but not for the overlay. if (mode == FSkyVertexBuffer::SKYMODE_MAINLAYER && tex != NULL) { - PalEntry pe = tex->tex->GetSkyCapColor(false); + auto base = tex->Source(); + PalEntry pe = base->GetSkyCapColor(false); state.SetObjectColor(pe); state.EnableTexture(false); RenderRow(di, state, DT_TriangleFan, 0); - pe = tex->tex->GetSkyCapColor(true); + pe = base->GetSkyCapColor(true); state.SetObjectColor(pe); RenderRow(di, state, DT_TriangleFan, rc); state.EnableTexture(true); @@ -96,7 +97,7 @@ void HWSkyPortal::RenderDome(HWDrawInfo *di, FRenderState &state, FMaterial * te void HWSkyPortal::RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texno, FMaterial * gltex, float x_offset, bool sky2) { - FSkyBox * sb = static_cast(gltex->tex); + FSkyBox * sb = static_cast(gltex->Source()); int faces; FMaterial * tex; @@ -181,7 +182,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) di->SetupView(state, 0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1)); state.SetVertexBuffer(vertexBuffer); - if (origin->texture[0] && origin->texture[0]->tex->isSkybox()) + if (origin->texture[0] && origin->texture[0]->Source()->isSkybox()) { RenderBox(di, state, origin->skytexno1, origin->texture[0], origin->x_offset[0], origin->sky2); } diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 151615935..fb96034ed 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -94,7 +94,7 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) // Optionally use STYLE_ColorBlend in place of STYLE_Add for fullbright items. if (RenderStyle == LegacyRenderStyles[STYLE_Add] && trans > 1.f - FLT_EPSILON && gl_usecolorblending && !di->isFullbrightScene() && actor && - fullbright && gltexture && !gltexture->tex->GetTranslucency()) + fullbright && gltexture && !gltexture->GetTranslucency()) { RenderStyle = LegacyRenderStyles[STYLE_ColorAdd]; } @@ -106,7 +106,7 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) { state.AlphaFunc(Alpha_GEqual, 0.f); } - else if (!gltexture || !gltexture->tex->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + else if (!gltexture || !gltexture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); else state.AlphaFunc(Alpha_Greater, 0.f); if (RenderStyle.BlendOp == STYLEOP_Shadow) @@ -914,7 +914,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t // allow disabling of the fullbright flag by a brightmap definition // (e.g. to do the gun flashes of Doom's zombies correctly. fullbright = (thing->flags5 & MF5_BRIGHT) || - ((thing->renderflags & RF_FULLBRIGHT) && (!gltexture || !gltexture->tex->isFullbrightDisabled())); + ((thing->renderflags & RF_FULLBRIGHT) && (!gltexture || !gltexture->Source()->isFullbrightDisabled())); lightlevel = fullbright ? 255 : hw_ClampLight(rendersector->GetTexture(sector_t::ceiling) == skyflatnum ? @@ -1033,7 +1033,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t RenderStyle.DestAlpha = STYLEALPHA_InvSrc; } } - if ((gltexture && gltexture->tex->GetTranslucency()) || (RenderStyle.Flags & STYLEF_RedIsAlpha) || (modelframe && thing->RenderStyle != DefaultRenderStyle())) + if ((gltexture && gltexture->GetTranslucency()) || (RenderStyle.Flags & STYLEF_RedIsAlpha) || (modelframe && thing->RenderStyle != DefaultRenderStyle())) { if (hw_styleflags == STYLEHW_Solid) { diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 5c527304b..1249a13ce 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -264,7 +264,7 @@ void HWWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state) state.SetRenderStyle(RenderStyle); if (gltexture) { - if (!gltexture->tex->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + if (!gltexture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); else state.AlphaFunc(Alpha_GEqual, 0.f); RenderTexturedWall(di, state, HWWall::RWF_TEXTURED | HWWall::RWF_NOSPLIT); } @@ -442,7 +442,7 @@ const char HWWall::passflag[] = { //========================================================================== void HWWall::PutWall(HWDrawInfo *di, bool translucent) { - if (gltexture && gltexture->tex->GetTranslucency() && passflag[type] == 2) + if (gltexture && gltexture->GetTranslucency() && passflag[type] == 2) { translucent = true; } @@ -1010,7 +1010,7 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto if (gltexture != NULL) { bool normalize = false; - if (gltexture->tex->isHardwareCanvas()) normalize = true; + if (gltexture->isHardwareCanvas()) normalize = true; else if (flags & HWF_CLAMPY) { // for negative scales we can get negative coordinates here. @@ -1039,7 +1039,7 @@ void HWWall::CheckTexturePosition(FTexCoordInfo *tci) { float sub; - if (gltexture->tex->isHardwareCanvas()) return; + if (gltexture->isHardwareCanvas()) return; // clamp texture coordinates to a reasonable range. // Extremely large values can cause visual problems @@ -1106,7 +1106,7 @@ void HWWall::CheckTexturePosition(FTexCoordInfo *tci) static void GetTexCoordInfo(FMaterial *tex, FTexCoordInfo *tci, side_t *side, int texpos) { - tci->GetFromTexture(tex->tex, (float)side->GetTextureXScale(texpos), (float)side->GetTextureYScale(texpos), !!(side->GetLevel()->flags3 & LEVEL3_FORCEWORLDPANNING)); + tci->GetFromTexture(tex->Source(), (float)side->GetTextureXScale(texpos), (float)side->GetTextureYScale(texpos), !!(side->GetLevel()->flags3 & LEVEL3_FORCEWORLDPANNING)); } //========================================================================== @@ -1412,7 +1412,7 @@ void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary, case 0: RenderStyle=STYLE_Translucent; alpha = seg->linedef->alpha; - translucent =alpha < 1. || (gltexture && gltexture->tex->GetTranslucency()); + translucent =alpha < 1. || (gltexture && gltexture->GetTranslucency()); break; case ML_ADDTRANS: @@ -2209,7 +2209,7 @@ void HWWall::ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t * frontsec { FTexCoordInfo tci; type = RENDERWALL_BOTTOM; - tci.GetFromTexture(gltexture->tex, 1, 1, false); + tci.GetFromTexture(gltexture->Source(), 1, 1, false); SetWallCoordinates(seg, &tci, bfh, bfh, bfh, ffh, ffh, 0); PutWall(di, false); } diff --git a/src/rendering/hwrenderer/scene/hw_weapon.cpp b/src/rendering/hwrenderer/scene/hw_weapon.cpp index d0de4e058..09881c100 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.cpp +++ b/src/rendering/hwrenderer/scene/hw_weapon.cpp @@ -94,7 +94,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state) } else { - float thresh = (huds->tex->tex->GetTranslucency() || huds->OverrideShader != -1) ? 0.f : gl_mask_sprite_threshold; + float thresh = (huds->tex->GetTranslucency() || huds->OverrideShader != -1) ? 0.f : gl_mask_sprite_threshold; state.AlphaFunc(Alpha_GEqual, thresh); state.SetMaterial(huds->tex, CLAMP_XY_NOMIP, (huds->weapon->Flags & PSPF_PLAYERTRANSLATED) ? huds->owner->Translation : 0, huds->OverrideShader); state.Draw(DT_TriangleStrip, huds->mx, 4); diff --git a/src/rendering/hwrenderer/textures/hw_precache.cpp b/src/rendering/hwrenderer/textures/hw_precache.cpp index fd42db857..9711fe74a 100644 --- a/src/rendering/hwrenderer/textures/hw_precache.cpp +++ b/src/rendering/hwrenderer/textures/hw_precache.cpp @@ -62,7 +62,7 @@ static void PrecacheTexture(FTexture *tex, int cache) //=========================================================================== static void PrecacheList(FMaterial *gltex, SpriteHits& translations) { - gltex->tex->SystemTextures.CleanUnused(translations, gltex->isExpanded()); + gltex->BaseLayer()->SystemTextures.CleanUnused(translations, gltex->isExpanded()); SpriteHits::Iterator it(translations); SpriteHits::Pair* pair; while (it.NextPair(pair)) screen->PrecacheMaterial(gltex, pair->Key); @@ -196,12 +196,15 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl FTexture *tex = TexMan.ByIndex(i); if (tex != nullptr) { - FMaterial *mat = FMaterial::ValidateTexture(tex, false, false); - if (mat != nullptr) + if (texhitlist[i] & (FTextureManager::HIT_Wall | FTextureManager::HIT_Flat | FTextureManager::HIT_Sky)) { - for (auto ftex : mat->GetLayerArray()) + FMaterial* mat = FMaterial::ValidateTexture(tex, false, false); + if (mat != nullptr) { - usedTextures.Insert(ftex, true); + for (auto ftex : mat->GetLayerArray()) + { + usedTextures.Insert(ftex, true); + } } } if (spritehitlist[i] != nullptr && (*spritehitlist[i]).CountUsed() > 0) @@ -226,11 +229,11 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl { if (usedTextures.CheckKey(tex) == nullptr) { - tex->SystemTextures.Clean(true, false); + tex->CleanHardwareTextures(true, false); } if (usedSprites.CheckKey(tex) == nullptr) { - tex->SystemTextures.Clean(false, true); + tex->CleanHardwareTextures(false, true); } } } diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 413106144..0e12a8275 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -535,13 +535,19 @@ void PolyFrameBuffer::CleanForRestart() void PolyFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) { - auto tex = mat->tex; - if (tex->isSWCanvas()) return; + if (mat->Source()->isSWCanvas()) return; int flags = mat->isExpanded() ? CTF_Expand : 0; - auto base = static_cast(mat->GetLayer(0, translation)); + FTexture* layer; + auto systex = static_cast(mat->GetLayer(0, translation, &layer)); + systex->GetImage(layer, translation, flags); - base->Precache(mat, translation, flags); + int numLayers = mat->GetLayers(); + for (int i = 1; i < numLayers; i++) + { + auto systex = static_cast(mat->GetLayer(i, 0, &layer)); + systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0); + } } IHardwareTexture *PolyFrameBuffer::CreateHardwareTexture() diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp index 73c063e95..b5d4d3e88 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -62,36 +62,15 @@ void PolyHardwareTexture::Reset() } } -void PolyHardwareTexture::Precache(FMaterial *mat, int translation, int flags) +DCanvas *PolyHardwareTexture::GetImage(FTexture *baselayer, const FMaterialState &state) { - int numLayers = mat->GetLayers(); - GetImage(mat->tex, translation, flags); - for (int i = 1; i < numLayers; i++) - { - FTexture *layer; - auto systex = static_cast(mat->GetLayer(i, 0, &layer)); - systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0); - } -} - -DCanvas *PolyHardwareTexture::GetImage(const FMaterialState &state) -{ - FTexture *tex = state.mMaterial->tex; + FTexture *tex = state.mMaterial->Source(); if (tex->isHardwareCanvas()) static_cast(tex)->NeedUpdate(); if (!mCanvas) { - FMaterial *mat = state.mMaterial; - int clampmode = state.mClampMode; - int translation = state.mTranslation; - - if (tex->UseType == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER; - if (tex->isHardwareCanvas()) clampmode = CLAMP_CAMTEX; - else if ((tex->isWarped() || tex->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; - int flags = state.mMaterial->isExpanded() ? CTF_Expand : 0; - - return GetImage(tex, translation, flags); + return GetImage(baselayer, state.mTranslation, flags); } return mCanvas.get(); diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.h b/src/rendering/polyrenderer/backend/poly_hwtexture.h index 3d7565b58..26d9beb5b 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.h +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.h @@ -23,9 +23,7 @@ public: static void ResetAll(); void Reset(); - void Precache(FMaterial *mat, int translation, int flags); - - DCanvas *GetImage(const FMaterialState &state); + DCanvas *GetImage(FTexture *tex, const FMaterialState &state); DCanvas *GetImage(FTexture *tex, int translation, int flags); PolyDepthStencil *GetDepthStencil(FTexture *tex); diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index cc763b89a..6a36105b5 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -280,8 +280,8 @@ void PolyRenderState::Apply() mDrawCommands->SetShader(EFF_NONE, mTextureEnabled ? effectState : SHADER_NoTexture, mAlphaThreshold >= 0.f, false); } - if (mMaterial.mMaterial && mMaterial.mMaterial->tex) - mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->tex->shaderspeed / 1000.); + if (mMaterial.mMaterial && mMaterial.mMaterial->Source()) + mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->shaderspeed / 1000.); else mStreamData.timer = 0.0f; @@ -312,12 +312,13 @@ void PolyRenderState::ApplyMaterial() { if (mMaterial.mChanged && mMaterial.mMaterial) { - mTempTM = mMaterial.mMaterial->tex->isHardwareCanvas() ? TM_OPAQUE : TM_NORMAL; + mTempTM = mMaterial.mMaterial->isHardwareCanvas() ? TM_OPAQUE : TM_NORMAL; - auto base = static_cast(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation)); + FTexture* layer; + auto base = static_cast(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation, &layer)); if (base) { - DCanvas *texcanvas = base->GetImage(mMaterial); + DCanvas *texcanvas = base->GetImage(layer, mMaterial); mDrawCommands->SetTexture(0, texcanvas->GetPixels(), texcanvas->GetWidth(), texcanvas->GetHeight(), texcanvas->IsBgra()); int numLayers = mMaterial.mMaterial->GetLayers(); diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index ca08b4134..b1d2b3e0c 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -337,8 +337,8 @@ void VkRenderState::ApplyStreamData() mStreamData.useVertexData = passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData; - if (mMaterial.mMaterial && mMaterial.mMaterial->tex) - mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->tex->shaderspeed / 1000.); + if (mMaterial.mMaterial && mMaterial.mMaterial->Source()) + mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->shaderspeed / 1000.); else mStreamData.timer = 0.0f; @@ -369,7 +369,7 @@ void VkRenderState::ApplyPushConstants() } int tempTM = TM_NORMAL; - if (mMaterial.mMaterial && mMaterial.mMaterial->tex && mMaterial.mMaterial->tex->isHardwareCanvas()) + if (mMaterial.mMaterial && mMaterial.mMaterial->isHardwareCanvas()) tempTM = TM_OPAQUE; mPushConstants.uFogEnabled = fogset; @@ -383,8 +383,11 @@ void VkRenderState::ApplyPushConstants() mPushConstants.uAlphaThreshold = mAlphaThreshold; mPushConstants.uClipSplit = { mClipSplit[0], mClipSplit[1] }; - if (mMaterial.mMaterial && mMaterial.mMaterial->tex) - mPushConstants.uSpecularMaterial = { mMaterial.mMaterial->tex->Glossiness, mMaterial.mMaterial->tex->SpecularLevel }; + if (mMaterial.mMaterial) + { + auto source = mMaterial.mMaterial->Source(); + mPushConstants.uSpecularMaterial = { source->Glossiness, source->SpecularLevel }; + } mPushConstants.uLightIndex = mLightIndex; mPushConstants.uDataIndex = mStreamBufferWriter.DataIndex(); diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 1c0ea5e6d..796526b7e 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -648,14 +648,21 @@ void VulkanFrameBuffer::CleanForRestart() void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) { - auto tex = mat->tex; - if (tex->isSWCanvas()) return; + if (mat->Source()->isSWCanvas()) return; // Textures that are already scaled in the texture lump will not get replaced by hires textures. int flags = mat->isExpanded() ? CTF_Expand : 0; - auto base = static_cast(mat->GetLayer(0, translation)); + FTexture* layer; - base->Precache(mat, translation, flags); + auto systex = static_cast(mat->GetLayer(0, translation, &layer)); + systex->GetImage(layer, translation, mat->isExpanded() ? CTF_Expand : 0); + + int numLayers = mat->GetLayers(); + for (int i = 1; i < numLayers; i++) + { + auto systex = static_cast(mat->GetLayer(i, 0, &layer)); + systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0); + } } IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture() diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index c8784b6c5..ccd7c804d 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -109,33 +109,21 @@ void VkHardwareTexture::ResetAllDescriptors() fb->GetRenderPassManager()->TextureSetPoolReset(); } -void VkHardwareTexture::Precache(FMaterial *mat, int translation, int flags) -{ - int numLayers = mat->GetLayers(); - GetImage(mat->tex, translation, flags); - for (int i = 1; i < numLayers; i++) - { - FTexture *layer; - auto systex = static_cast(mat->GetLayer(i, 0, &layer)); - systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0); - } -} - VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &state) { FMaterial *mat = state.mMaterial; - FTexture *tex = state.mMaterial->tex; + FTexture *base = state.mMaterial->Source(); int clampmode = state.mClampMode; int translation = state.mTranslation; - if (tex->UseType == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER; - if (tex->isHardwareCanvas()) clampmode = CLAMP_CAMTEX; - else if ((tex->isWarped() || tex->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; + if (base->UseType == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER; + if (base->isHardwareCanvas()) clampmode = CLAMP_CAMTEX; + else if ((base->isWarped() || base->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; // Textures that are already scaled in the texture lump will not get replaced by hires textures. int flags = state.mMaterial->isExpanded() ? CTF_Expand : 0; - if (tex->isHardwareCanvas()) static_cast(tex)->NeedUpdate(); + if (base->isHardwareCanvas()) static_cast(base)->NeedUpdate(); for (auto &set : mDescriptorSets) { @@ -152,7 +140,7 @@ VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &s VulkanSampler *sampler = fb->GetSamplerManager()->Get(clampmode); WriteDescriptors update; - update.addCombinedImageSampler(descriptor.get(), 0, GetImage(tex, translation, flags)->View.get(), sampler, mImage.Layout); + update.addCombinedImageSampler(descriptor.get(), 0, GetImage(mat->BaseLayer(), translation, flags)->View.get(), sampler, mImage.Layout); for (int i = 1; i < numLayers; i++) { FTexture *layer; diff --git a/src/rendering/vulkan/textures/vk_hwtexture.h b/src/rendering/vulkan/textures/vk_hwtexture.h index 6dd2f8ea9..b7bd02979 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/rendering/vulkan/textures/vk_hwtexture.h @@ -27,8 +27,6 @@ public: static void ResetAll(); void Reset(); - void Precache(FMaterial *mat, int translation, int flags); - VulkanDescriptorSet *GetDescriptorSet(const FMaterialState &state); // Software renderer stuff