Vulkan: Add a memory allocator and hook it up to the texture cache.

This commit is contained in:
DrChat 2017-08-20 20:48:36 -05:00
parent 7e819a4ccb
commit 4e4a1a03c1
4 changed files with 5461 additions and 24 deletions

View File

@ -18,6 +18,8 @@
#include "xenia/gpu/texture_info.h"
#include "xenia/gpu/vulkan/vulkan_gpu_flags.h"
#include "third_party/vulkan/vk_mem_alloc.h"
namespace xe {
namespace gpu {
namespace vulkan {
@ -70,6 +72,8 @@ static const TextureConfig texture_configs[64] = {
/* k_16_FLOAT */ {VK_FORMAT_R16_SFLOAT},
/* k_16_16_FLOAT */ {VK_FORMAT_R16G16_SFLOAT},
/* k_16_16_16_16_FLOAT */ {VK_FORMAT_R16G16B16A16_SFLOAT},
// ! These are UNORM formats, not SINT.
/* k_32 */ {VK_FORMAT_R32_SINT},
/* k_32_32 */ {VK_FORMAT_R32G32_SINT},
/* k_32_32_32_32 */ {VK_FORMAT_R32G32B32A32_SINT},
@ -184,6 +188,13 @@ TextureCache::TextureCache(Memory* memory, RegisterFile* register_file,
assert_always();
}
// Create a memory allocator for textures.
VmaAllocatorCreateInfo alloc_info = {
0, *device_, *device_, 0, 0, nullptr, nullptr,
};
err = vmaCreateAllocator(&alloc_info, &mem_allocator_);
CheckResult(err, "vmaCreateAllocator");
invalidated_textures_sets_[0].reserve(64);
invalidated_textures_sets_[1].reserve(64);
invalidated_textures_ = &invalidated_textures_sets_[0];
@ -273,34 +284,26 @@ TextureCache::Texture* TextureCache::AllocateTexture(
image_info.pQueueFamilyIndices = nullptr;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImage image;
auto err = vkCreateImage(*device_, &image_info, nullptr, &image);
CheckResult(err, "vkCreateImage");
VkMemoryRequirements mem_requirements;
vkGetImageMemoryRequirements(*device_, image, &mem_requirements);
// TODO: Use a circular buffer or something else to allocate this memory.
// The device has a limited amount (around 64) of memory allocations that we
// can make.
// Now that we have the size, back the image with GPU memory.
auto memory = device_->AllocateMemory(mem_requirements, 0);
if (!memory) {
VmaAllocation alloc;
VmaMemoryRequirements vma_reqs = {
0, VMA_MEMORY_USAGE_GPU_ONLY, 0, 0, nullptr,
};
VmaAllocationInfo vma_info = {};
VkResult status = vmaCreateImage(mem_allocator_, &image_info, &vma_reqs,
&image, &alloc, &vma_info);
if (status != VK_SUCCESS) {
// Crap.
assert_always();
vkDestroyImage(*device_, image, nullptr);
return nullptr;
}
err = vkBindImageMemory(*device_, image, memory, 0);
CheckResult(err, "vkBindImageMemory");
auto texture = new Texture();
texture->format = image_info.format;
texture->image = image;
texture->image_layout = image_info.initialLayout;
texture->image_memory = memory;
texture->memory_offset = 0;
texture->memory_size = mem_requirements.size;
texture->alloc = alloc;
texture->alloc_info = vma_info;
texture->framebuffer = nullptr;
texture->access_watch_handle = 0;
texture->texture_info = texture_info;
@ -328,8 +331,7 @@ bool TextureCache::FreeTexture(Texture* texture) {
texture->access_watch_handle = 0;
}
vkDestroyImage(*device_, texture->image, nullptr);
vkFreeMemory(*device_, texture->image_memory, nullptr);
vmaDestroyImage(mem_allocator_, texture->image, texture->alloc);
delete texture;
return true;
}
@ -1084,7 +1086,7 @@ bool TextureCache::ComputeTextureStorage(size_t* output_length,
void TextureCache::WritebackTexture(Texture* texture) {
VkResult status = VK_SUCCESS;
VkFence fence = wb_command_pool_->BeginBatch();
auto alloc = wb_staging_buffer_.Acquire(texture->memory_size, fence);
auto alloc = wb_staging_buffer_.Acquire(texture->alloc_info.size, fence);
if (!alloc) {
wb_command_pool_->EndBatch();
return;

View File

@ -24,6 +24,8 @@
#include "xenia/ui/vulkan/vulkan.h"
#include "xenia/ui/vulkan/vulkan_device.h"
#include "third_party/vulkan/vk_mem_alloc.h"
namespace xe {
namespace gpu {
namespace vulkan {
@ -41,9 +43,8 @@ class TextureCache {
VkFormat format;
VkImage image;
VkImageLayout image_layout;
VkDeviceMemory image_memory;
VkDeviceSize memory_offset;
VkDeviceSize memory_size;
VmaAllocation alloc;
VmaAllocationInfo alloc_info;
VkFramebuffer framebuffer; // Blit target frame buffer.
uintptr_t access_watch_handle;
@ -187,6 +188,8 @@ class TextureCache {
std::unordered_map<uint64_t, VkDescriptorSet> texture_bindings_;
VkDescriptorSetLayout texture_descriptor_set_layout_ = nullptr;
VmaAllocator mem_allocator_ = nullptr;
ui::vulkan::CircularBuffer staging_buffer_;
ui::vulkan::CircularBuffer wb_staging_buffer_;
std::unordered_map<uint64_t, Texture*> textures_;

View File

@ -12,6 +12,10 @@
#include "xenia/base/assert.h"
#include "xenia/base/logging.h"
// Implement AMD's VMA here.
#define VMA_IMPLEMENTATION
#include "third_party/vulkan/vk_mem_alloc.h"
namespace xe {
namespace ui {
namespace vulkan {

5428
third_party/vulkan/vk_mem_alloc.h vendored Normal file

File diff suppressed because it is too large Load Diff