vk: use-after-free if inFlight texture is deleted or cache cleared

This commit is contained in:
Flyinghead 2020-11-24 18:01:09 +01:00
parent 370c470bd9
commit 7744e1a262
3 changed files with 22 additions and 6 deletions

View File

@ -772,6 +772,8 @@ public:
return texture;
}
virtual ~BaseTextureCache() {}
void CollectCleanup()
{
std::vector<u64> list;
@ -789,7 +791,7 @@ public:
for (u64 id : list)
{
if (cache[id].Delete())
if (clearTexture(&cache[id]))
cache.erase(id);
}
}
@ -797,13 +799,18 @@ public:
void Clear()
{
for (auto& pair : cache)
pair.second.Delete();
clearTexture(&pair.second);
cache.clear();
KillTex = false;
INFO_LOG(RENDERER, "Texture cache cleared");
}
protected:
virtual bool clearTexture(Texture *tex) {
return tex->Delete();
}
private:
std::unordered_map<u64, Texture> cache;
// Only use TexU and TexV from TSP in the cache key

View File

@ -218,7 +218,7 @@ extern struct ShaderUniforms_t
} ShaderUniforms;
class TextureCacheData : public BaseTextureCacheData
class TextureCacheData final : public BaseTextureCacheData
{
public:
GLuint texID; //gl texture
@ -227,7 +227,7 @@ public:
virtual bool Delete() override;
};
class TextureCache : public BaseTextureCache<TextureCacheData>
class TextureCache final : public BaseTextureCache<TextureCacheData>
{
};
extern TextureCache TexCache;

View File

@ -33,7 +33,7 @@
void setImageLayout(vk::CommandBuffer const& commandBuffer, vk::Image image, vk::Format format, u32 mipmapLevels, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout);
class Texture : public BaseTextureCacheData
class Texture final : public BaseTextureCacheData
{
public:
void UploadToGPU(int width, int height, u8 *data, bool mipmapped, bool mipmapsIncluded = false) override;
@ -134,7 +134,7 @@ private:
vk::Device device;
};
class TextureCache : public BaseTextureCache<Texture>
class TextureCache final : public BaseTextureCache<Texture>
{
public:
void SetCurrentIndex(int index) {
@ -173,6 +173,15 @@ public:
texture->format = vk::Format::eUndefined;
}
protected:
virtual bool clearTexture(Texture *tex) override
{
std::for_each(inFlightTextures.begin(), inFlightTextures.end(),
[tex](std::unordered_set<Texture *>& set) { set.erase(tex); });
return BaseTextureCache<Texture>::clearTexture(tex);
}
private:
template<typename T>
void EmptyTrash(T& v)