Vulkan: Add a memory allocator and hook it up to the texture cache.
This commit is contained in:
parent
7e819a4ccb
commit
4e4a1a03c1
|
@ -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;
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue