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/texture_info.h"
#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" #include "xenia/gpu/vulkan/vulkan_gpu_flags.h"
#include "third_party/vulkan/vk_mem_alloc.h"
namespace xe { namespace xe {
namespace gpu { namespace gpu {
namespace vulkan { namespace vulkan {
@ -70,6 +72,8 @@ static const TextureConfig texture_configs[64] = {
/* k_16_FLOAT */ {VK_FORMAT_R16_SFLOAT}, /* k_16_FLOAT */ {VK_FORMAT_R16_SFLOAT},
/* k_16_16_FLOAT */ {VK_FORMAT_R16G16_SFLOAT}, /* k_16_16_FLOAT */ {VK_FORMAT_R16G16_SFLOAT},
/* k_16_16_16_16_FLOAT */ {VK_FORMAT_R16G16B16A16_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 */ {VK_FORMAT_R32_SINT},
/* k_32_32 */ {VK_FORMAT_R32G32_SINT}, /* k_32_32 */ {VK_FORMAT_R32G32_SINT},
/* k_32_32_32_32 */ {VK_FORMAT_R32G32B32A32_SINT}, /* k_32_32_32_32 */ {VK_FORMAT_R32G32B32A32_SINT},
@ -184,6 +188,13 @@ TextureCache::TextureCache(Memory* memory, RegisterFile* register_file,
assert_always(); 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_[0].reserve(64);
invalidated_textures_sets_[1].reserve(64); invalidated_textures_sets_[1].reserve(64);
invalidated_textures_ = &invalidated_textures_sets_[0]; invalidated_textures_ = &invalidated_textures_sets_[0];
@ -273,34 +284,26 @@ TextureCache::Texture* TextureCache::AllocateTexture(
image_info.pQueueFamilyIndices = nullptr; image_info.pQueueFamilyIndices = nullptr;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImage image; VkImage image;
auto err = vkCreateImage(*device_, &image_info, nullptr, &image);
CheckResult(err, "vkCreateImage");
VkMemoryRequirements mem_requirements; VmaAllocation alloc;
vkGetImageMemoryRequirements(*device_, image, &mem_requirements); VmaMemoryRequirements vma_reqs = {
0, VMA_MEMORY_USAGE_GPU_ONLY, 0, 0, nullptr,
// 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 VmaAllocationInfo vma_info = {};
// can make. VkResult status = vmaCreateImage(mem_allocator_, &image_info, &vma_reqs,
// Now that we have the size, back the image with GPU memory. &image, &alloc, &vma_info);
auto memory = device_->AllocateMemory(mem_requirements, 0); if (status != VK_SUCCESS) {
if (!memory) {
// Crap. // Crap.
assert_always(); assert_always();
vkDestroyImage(*device_, image, nullptr);
return nullptr; return nullptr;
} }
err = vkBindImageMemory(*device_, image, memory, 0);
CheckResult(err, "vkBindImageMemory");
auto texture = new Texture(); auto texture = new Texture();
texture->format = image_info.format; texture->format = image_info.format;
texture->image = image; texture->image = image;
texture->image_layout = image_info.initialLayout; texture->image_layout = image_info.initialLayout;
texture->image_memory = memory; texture->alloc = alloc;
texture->memory_offset = 0; texture->alloc_info = vma_info;
texture->memory_size = mem_requirements.size;
texture->framebuffer = nullptr; texture->framebuffer = nullptr;
texture->access_watch_handle = 0; texture->access_watch_handle = 0;
texture->texture_info = texture_info; texture->texture_info = texture_info;
@ -328,8 +331,7 @@ bool TextureCache::FreeTexture(Texture* texture) {
texture->access_watch_handle = 0; texture->access_watch_handle = 0;
} }
vkDestroyImage(*device_, texture->image, nullptr); vmaDestroyImage(mem_allocator_, texture->image, texture->alloc);
vkFreeMemory(*device_, texture->image_memory, nullptr);
delete texture; delete texture;
return true; return true;
} }
@ -1084,7 +1086,7 @@ bool TextureCache::ComputeTextureStorage(size_t* output_length,
void TextureCache::WritebackTexture(Texture* texture) { void TextureCache::WritebackTexture(Texture* texture) {
VkResult status = VK_SUCCESS; VkResult status = VK_SUCCESS;
VkFence fence = wb_command_pool_->BeginBatch(); 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) { if (!alloc) {
wb_command_pool_->EndBatch(); wb_command_pool_->EndBatch();
return; return;

View File

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

View File

@ -12,6 +12,10 @@
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/logging.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 xe {
namespace ui { namespace ui {
namespace vulkan { namespace vulkan {

5428
third_party/vulkan/vk_mem_alloc.h vendored Normal file

File diff suppressed because it is too large Load Diff