diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 216522166..37a7bead4 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -80,7 +80,8 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, VulkanDeviceAllocator *all if (allocator && !dedicatedAllocation) { allocator_ = allocator; - offset_ = allocator_->Allocate(mem_reqs, &mem_, Tag()); + // ok to use the tag like this, because the lifetime of the VulkanImage exceeds that of the allocation. + offset_ = allocator_->Allocate(mem_reqs, &mem_, Tag().c_str()); if (offset_ == VulkanDeviceAllocator::ALLOCATE_FAILED) { ERROR_LOG(G3D, "Image memory allocation failed (mem_reqs.size=%d, typebits=%08x", (int)mem_reqs.size, (int)mem_reqs.memoryTypeBits); // Destructor will take care of the image. diff --git a/Common/Vulkan/VulkanImage.h b/Common/Vulkan/VulkanImage.h index 91e36dc97..e16ceccc8 100644 --- a/Common/Vulkan/VulkanImage.h +++ b/Common/Vulkan/VulkanImage.h @@ -30,10 +30,10 @@ public: void Destroy(); - void SetTag(const std::string &tag) { + void SetTag(const char *tag) { tag_ = tag; } - std::string Tag() const { + const std::string &Tag() const { return tag_; } void Touch(); diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index 6698c73e2..74cd1cb66 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -191,7 +191,7 @@ void VulkanDeviceAllocator::Destroy() { destroyed_ = true; } -size_t VulkanDeviceAllocator::Allocate(const VkMemoryRequirements &reqs, VkDeviceMemory *deviceMemory, const std::string &tag) { +size_t VulkanDeviceAllocator::Allocate(const VkMemoryRequirements &reqs, VkDeviceMemory *deviceMemory, const char *tag) { _assert_(!destroyed_); uint32_t memoryTypeIndex; bool pass = vulkan_->MemoryTypeFromProperties(reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memoryTypeIndex); @@ -244,7 +244,7 @@ size_t VulkanDeviceAllocator::Allocate(const VkMemoryRequirements &reqs, VkDevic return ALLOCATE_FAILED; } -bool VulkanDeviceAllocator::AllocateFromSlab(Slab &slab, size_t &start, size_t blocks, const std::string &tag) { +bool VulkanDeviceAllocator::AllocateFromSlab(Slab &slab, size_t &start, size_t blocks, const char *tag) { _assert_(!destroyed_); bool matched = true; @@ -278,7 +278,7 @@ bool VulkanDeviceAllocator::AllocateFromSlab(Slab &slab, size_t &start, size_t b // Remember the size so we can free. slab.allocSizes[start] = blocks; - slab.tags[start] = { tag, time_now_d(), 0.0 }; + slab.tags[start] = { time_now_d(), 0.0, tag }; slab.totalUsage += blocks; return true; } @@ -442,7 +442,7 @@ void VulkanDeviceAllocator::ReportOldUsage() { const auto &slab = slabs_[i]; bool hasOldAllocs = false; - for (auto it : slab.tags) { + for (auto &it : slab.tags) { const auto info = it.second; double touchedAge = now - info.touched; if (touchedAge >= OLD_AGE) { @@ -453,12 +453,12 @@ void VulkanDeviceAllocator::ReportOldUsage() { if (hasOldAllocs) { NOTICE_LOG(G3D, "Slab %d usage:", (int)i); - for (auto it : slab.tags) { + for (auto &it : slab.tags) { const auto info = it.second; double createAge = now - info.created; double touchedAge = now - info.touched; - NOTICE_LOG(G3D, " * %s (created %fs ago, used %fs ago)", info.tag.c_str(), createAge, touchedAge); + NOTICE_LOG(G3D, " * %s (created %fs ago, used %fs ago)", info.tag, createAge, touchedAge); } } } diff --git a/Common/Vulkan/VulkanMemory.h b/Common/Vulkan/VulkanMemory.h index 31ddc25fa..54b41aed7 100644 --- a/Common/Vulkan/VulkanMemory.h +++ b/Common/Vulkan/VulkanMemory.h @@ -149,7 +149,8 @@ public: } // May return ALLOCATE_FAILED if the allocation fails. - size_t Allocate(const VkMemoryRequirements &reqs, VkDeviceMemory *deviceMemory, const std::string &tag); + // NOTE: Lifetime of the string tag points to must exceed that of the allocation. + size_t Allocate(const VkMemoryRequirements &reqs, VkDeviceMemory *deviceMemory, const char *tag); // Crashes on a double or misfree. void Free(VkDeviceMemory deviceMemory, size_t offset); @@ -177,9 +178,9 @@ private: static const uint32_t UNDEFINED_MEMORY_TYPE = -1; struct UsageInfo { - std::string tag; double created; double touched; + const char *tag; }; struct Slab { @@ -212,7 +213,7 @@ private: } bool AllocateSlab(VkDeviceSize minBytes, int memoryTypeIndex); - bool AllocateFromSlab(Slab &slab, size_t &start, size_t blocks, const std::string &tag); + bool AllocateFromSlab(Slab &slab, size_t &start, size_t blocks, const char *tag); void Decimate(); void DoTouch(VkDeviceMemory deviceMemory, size_t offset); void ExecuteFree(FreeInfo *userdata); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 56b850852..1e43e6a0c 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1753,6 +1753,9 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) { void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type) { // They could invalidate inside the texture, let's just give a bit of leeway. + // TODO: Keep track of the largest texture size in bytes, and use that instead of this + // humongous unrealistic value. + const int LARGEST_TEXTURE_SIZE = 512 * 512 * 4; addr &= 0x3FFFFFFF; @@ -1785,7 +1788,8 @@ void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type u32 texAddr = iter->second->addr; u32 texEnd = iter->second->addr + iter->second->sizeInRAM; - if (texAddr < addr_end && addr < texEnd) { + // Quick check for overlap. Yes the check is right. + if (addr < texEnd && addr_end > texAddr) { if (iter->second->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { iter->second->SetHashStatus(TexCacheEntry::STATUS_HASHING); } diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index c5a8753d0..48eae6270 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -193,6 +193,7 @@ void GPU_D3D11::BuildReportingInfo() { } void GPU_D3D11::DeviceLost() { + draw_->InvalidateCachedState(); // Simply drop all caches and textures. // FBOs appear to survive? Or no? shaderManagerD3D11_->ClearShaders();