Vulkan: Use the slab allocator for textures.

This commit is contained in:
Unknown W. Brackets 2016-03-26 18:22:21 -07:00
parent 62b6432121
commit 27a5697a96
4 changed files with 44 additions and 16 deletions

View file

@ -1,4 +1,5 @@
#include "Common/Vulkan/VulkanImage.h"
#include "Common/Vulkan/VulkanMemory.h"
VkResult VulkanTexture::Create(int w, int h, VkFormat format) {
tex_width = w;
@ -234,9 +235,12 @@ void VulkanTexture::Wipe() {
vulkan_->Delete().QueueDeleteImageView(view);
view = VK_NULL_HANDLE;
}
if (mem) {
if (mem && !allocator_) {
vulkan_->Delete().QueueDeleteDeviceMemory(mem);
mem = VK_NULL_HANDLE;
} else if (mem) {
allocator_->Free(mem, offset_);
mem = VK_NULL_HANDLE;
}
}
@ -267,18 +271,25 @@ void VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format, VkI
assert(res == VK_SUCCESS);
vkGetImageMemoryRequirements(vulkan_->GetDevice(), image, &mem_reqs);
VkMemoryAllocateInfo mem_alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
mem_alloc.memoryTypeIndex = 0;
mem_alloc.allocationSize = mem_reqs.size;
// Find memory type - don't specify any mapping requirements
bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex);
assert(pass);
if (allocator_) {
offset_ = allocator_->Allocate(mem_reqs, &mem);
} else {
VkMemoryAllocateInfo mem_alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
mem_alloc.memoryTypeIndex = 0;
mem_alloc.allocationSize = mem_reqs.size;
res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem);
assert(res == VK_SUCCESS);
// Find memory type - don't specify any mapping requirements
bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex);
assert(pass);
res = vkBindImageMemory(vulkan_->GetDevice(), image, mem, 0);
res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem);
assert(res == VK_SUCCESS);
offset_ = 0;
}
res = vkBindImageMemory(vulkan_->GetDevice(), image, mem, offset_);
assert(res == VK_SUCCESS);
// Since we're going to blit to the target, set its layout to TRANSFER_DST
@ -347,11 +358,13 @@ void VulkanTexture::Destroy() {
mappableImage = VK_NULL_HANDLE;
}
}
if (mem) {
if (mem && !allocator_) {
vulkan_->Delete().QueueDeleteDeviceMemory(mem);
if (mappableMemory == mem) {
mappableMemory = VK_NULL_HANDLE;
}
} else if (mem) {
allocator_->Free(mem, offset_);
}
view = VK_NULL_HANDLE;

View file

@ -2,14 +2,17 @@
#include "Common/Vulkan/VulkanContext.h"
class VulkanDeviceAllocator;
// Wrapper around what you need to use a texture.
// Not very optimal - if you have many small textures you should use other strategies.
class VulkanTexture {
public:
VulkanTexture(VulkanContext *vulkan)
VulkanTexture(VulkanContext *vulkan, VulkanDeviceAllocator *allocator = nullptr)
: vulkan_(vulkan), image(VK_NULL_HANDLE), mem(VK_NULL_HANDLE), view(VK_NULL_HANDLE),
tex_width(0), tex_height(0), numMips_(1), format_(VK_FORMAT_UNDEFINED),
mappableImage(VK_NULL_HANDLE), mappableMemory(VK_NULL_HANDLE), needStaging(false) {
mappableImage(VK_NULL_HANDLE), mappableMemory(VK_NULL_HANDLE), needStaging(false),
allocator_(allocator), offset_(0) {
memset(&mem_reqs, 0, sizeof(mem_reqs));
}
~VulkanTexture() {
@ -47,4 +50,6 @@ private:
VkDeviceMemory mappableMemory;
VkMemoryRequirements mem_reqs;
bool needStaging;
VulkanDeviceAllocator *allocator_;
size_t offset_;
};

View file

@ -66,8 +66,11 @@
#define TEXCACHE_MAX_TEXELS_SCALED (256*256) // Per frame
#define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in GL
#define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024
#define TEXCACHE_MIN_PRESSURE (16 * 1024 * 1024) // Total in GL
#define TEXCACHE_SECOND_MIN_PRESSURE (4 * 1024 * 1024)
#define TEXCACHE_MIN_SLAB_SIZE (4 * 1024 * 1024)
#define TEXCACHE_MAX_SLAB_SIZE (32 * 1024 * 1024)
// Note: some drivers prefer B4G4R4A4_UNORM_PACK16 over R4G4B4A4_UNORM_PACK16.
#define VULKAN_4444_FORMAT VK_FORMAT_B4G4R4A4_UNORM_PACK16
@ -137,6 +140,7 @@ TextureCacheVulkan::TextureCacheVulkan(VulkanContext *vulkan)
timesInvalidatedAllThisFrame_ = 0;
lastBoundTexture = nullptr;
decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL;
allocator_ = new VulkanDeviceAllocator(vulkan_, TEXCACHE_MIN_SLAB_SIZE, TEXCACHE_MAX_SLAB_SIZE);
SetupTextureDecoder();
@ -559,6 +563,8 @@ void TextureCacheVulkan::SetFramebufferSamplingParams(u16 bufferWidth, u16 buffe
}
void TextureCacheVulkan::StartFrame() {
// TODO: Better place?
allocator_->End();
lastBoundTexture = nullptr;
timesInvalidatedAllThisFrame_ = 0;
@ -572,6 +578,8 @@ void TextureCacheVulkan::StartFrame() {
} else {
Decimate();
}
allocator_->Begin();
}
static inline u32 MiniHash(const u32 *ptr) {
@ -1318,7 +1326,7 @@ void TextureCacheVulkan::SetTexture(VulkanPushBuffer *uploadBuffer) {
}
} else {
entry->vkTex = new CachedTextureVulkan();
entry->vkTex->texture_ = new VulkanTexture(vulkan_);
entry->vkTex->texture_ = new VulkanTexture(vulkan_, allocator_);
VulkanTexture *image = entry->vkTex->texture_;
const VkComponentMapping *mapping;

View file

@ -35,6 +35,7 @@ class DrawEngineVulkan;
class VulkanContext;
class VulkanTexture;
class VulkanPushBuffer;
class VulkanDeviceAllocator;
struct SamplerCacheKey {
SamplerCacheKey() : fullKey(0) {}
@ -140,6 +141,7 @@ private:
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key);
VulkanContext *vulkan_;
VulkanDeviceAllocator *allocator_;
TexCache secondCache;
u32 secondCacheSizeEstimate_;