vkd3d: Add a memory budget per memory type.
For resizable BAR, we don't want to endlessly promote UPLOAD heaps to BAR since VRAM is precious. The aim is to set a fixed budget where we can keep allocating until full, at which point we fall back to plain HOST. Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
parent
e0451bb541
commit
abdaeb136d
|
@ -2529,6 +2529,7 @@ static void d3d12_device_destroy(struct d3d12_device *device)
|
|||
vkd3d_private_store_destroy(&device->private_store);
|
||||
|
||||
vkd3d_cleanup_format_info(device);
|
||||
vkd3d_memory_info_cleanup(&device->memory_info, device);
|
||||
vkd3d_shader_debug_ring_cleanup(&device->debug_ring, device);
|
||||
d3d12_device_global_pipeline_cache_cleanup(device);
|
||||
vkd3d_sampler_state_cleanup(&device->sampler_state, device);
|
||||
|
@ -5229,7 +5230,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
|
|||
goto out_cleanup_format_info;
|
||||
|
||||
if (FAILED(hr = vkd3d_bindless_state_init(&device->bindless_state, device)))
|
||||
goto out_cleanup_format_info;
|
||||
goto out_cleanup_memory_info;
|
||||
|
||||
if (FAILED(hr = vkd3d_view_map_init(&device->sampler_map)))
|
||||
goto out_cleanup_bindless_state;
|
||||
|
@ -5273,6 +5274,8 @@ out_cleanup_view_map:
|
|||
vkd3d_view_map_destroy(&device->sampler_map, device);
|
||||
out_cleanup_bindless_state:
|
||||
vkd3d_bindless_state_cleanup(&device->bindless_state, device);
|
||||
out_cleanup_memory_info:
|
||||
vkd3d_memory_info_cleanup(&device->memory_info, device);
|
||||
out_cleanup_format_info:
|
||||
vkd3d_cleanup_format_info(device);
|
||||
out_free_memory_allocator:
|
||||
|
|
|
@ -143,17 +143,34 @@ static HRESULT vkd3d_create_global_buffer(struct d3d12_device *device, VkDeviceS
|
|||
void vkd3d_free_device_memory(struct d3d12_device *device, const struct vkd3d_device_memory_allocation *allocation)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
VkDeviceSize *type_current;
|
||||
bool budget_sensitive;
|
||||
|
||||
VK_CALL(vkFreeMemory(device->vk_device, allocation->vk_memory, NULL));
|
||||
budget_sensitive = !!(device->memory_info.budget_sensitive_mask & (1u << allocation->vk_memory_type));
|
||||
if (budget_sensitive)
|
||||
{
|
||||
type_current = &device->memory_info.type_current[allocation->vk_memory_type];
|
||||
pthread_mutex_lock(&device->memory_info.budget_lock);
|
||||
assert(*type_current >= allocation->size);
|
||||
*type_current -= allocation->size;
|
||||
pthread_mutex_unlock(&device->memory_info.budget_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT vkd3d_try_allocate_device_memory(struct d3d12_device *device,
|
||||
VkDeviceSize size, VkMemoryPropertyFlags type_flags, uint32_t type_mask,
|
||||
void *pNext, struct vkd3d_device_memory_allocation *allocation)
|
||||
{
|
||||
const VkPhysicalDeviceMemoryProperties *memory_props = &device->memory_properties;
|
||||
const VkMemoryPropertyFlags optional_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
const VkPhysicalDeviceMemoryProperties *memory_info = &device->memory_properties;
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
struct vkd3d_memory_info *memory_info = &device->memory_info;
|
||||
VkMemoryAllocateInfo allocate_info;
|
||||
VkDeviceSize *type_current;
|
||||
VkDeviceSize *type_budget;
|
||||
bool budget_sensitive;
|
||||
VkResult vr;
|
||||
|
||||
/* buffer_mask / sampled_mask etc will generally take care of this,
|
||||
* but for certain fallback scenarios where we select other memory
|
||||
|
@ -168,12 +185,36 @@ static HRESULT vkd3d_try_allocate_device_memory(struct d3d12_device *device,
|
|||
{
|
||||
uint32_t type_index = vkd3d_bitmask_iter32(&type_mask);
|
||||
|
||||
if ((memory_info->memoryTypes[type_index].propertyFlags & type_flags) != type_flags)
|
||||
if ((memory_props->memoryTypes[type_index].propertyFlags & type_flags) != type_flags)
|
||||
continue;
|
||||
|
||||
allocate_info.memoryTypeIndex = type_index;
|
||||
|
||||
if (VK_CALL(vkAllocateMemory(device->vk_device, &allocate_info, NULL, &allocation->vk_memory)) == VK_SUCCESS)
|
||||
budget_sensitive = !!(device->memory_info.budget_sensitive_mask & (1u << type_index));
|
||||
if (budget_sensitive)
|
||||
{
|
||||
type_budget = &memory_info->type_budget[type_index];
|
||||
type_current = &memory_info->type_current[type_index];
|
||||
pthread_mutex_lock(&memory_info->budget_lock);
|
||||
if (*type_current + size > *type_budget)
|
||||
{
|
||||
WARN("Attempting to allocate from memory type %u, but exceeding fixed budget: %"PRIu64" + %"PRIu64" > %"PRIu64".\n",
|
||||
type_index, *type_current, size, *type_budget);
|
||||
pthread_mutex_unlock(&memory_info->budget_lock);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
vr = VK_CALL(vkAllocateMemory(device->vk_device, &allocate_info, NULL, &allocation->vk_memory));
|
||||
|
||||
if (budget_sensitive)
|
||||
{
|
||||
if (vr == VK_SUCCESS)
|
||||
*type_current += size;
|
||||
pthread_mutex_unlock(&memory_info->budget_lock);
|
||||
}
|
||||
|
||||
if (vr == VK_SUCCESS)
|
||||
{
|
||||
allocation->vk_memory_type = type_index;
|
||||
allocation->size = size;
|
||||
|
|
|
@ -5971,6 +5971,12 @@ static uint32_t vkd3d_memory_info_find_global_mask(struct d3d12_device *device)
|
|||
return ~mask;
|
||||
}
|
||||
|
||||
void vkd3d_memory_info_cleanup(struct vkd3d_memory_info *info,
|
||||
struct d3d12_device *device)
|
||||
{
|
||||
pthread_mutex_destroy(&info->budget_lock);
|
||||
}
|
||||
|
||||
HRESULT vkd3d_memory_info_init(struct vkd3d_memory_info *info,
|
||||
struct d3d12_device *device)
|
||||
{
|
||||
|
@ -5991,6 +5997,9 @@ HRESULT vkd3d_memory_info_init(struct vkd3d_memory_info *info,
|
|||
|
||||
info->global_mask = vkd3d_memory_info_find_global_mask(device);
|
||||
|
||||
if (pthread_mutex_init(&info->budget_lock, NULL) != 0)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
memset(&buffer_info, 0, sizeof(buffer_info));
|
||||
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buffer_info.size = 65536;
|
||||
|
|
|
@ -2226,6 +2226,11 @@ struct vkd3d_memory_info_domain
|
|||
uint32_t buffer_type_mask;
|
||||
uint32_t sampled_type_mask;
|
||||
uint32_t rt_ds_type_mask;
|
||||
|
||||
uint32_t budget_sensitive_mask;
|
||||
VkDeviceSize type_budget[VK_MAX_MEMORY_TYPES];
|
||||
VkDeviceSize type_current[VK_MAX_MEMORY_TYPES];
|
||||
pthread_mutex_t budget_lock;
|
||||
};
|
||||
|
||||
struct vkd3d_memory_info
|
||||
|
@ -2245,6 +2250,8 @@ struct vkd3d_memory_info
|
|||
|
||||
HRESULT vkd3d_memory_info_init(struct vkd3d_memory_info *info,
|
||||
struct d3d12_device *device);
|
||||
void vkd3d_memory_info_cleanup(struct vkd3d_memory_info *info,
|
||||
struct d3d12_device *device);
|
||||
|
||||
/* meta operations */
|
||||
struct vkd3d_clear_uav_args
|
||||
|
|
Loading…
Reference in New Issue