|
|
|
@ -72,6 +72,11 @@ namespace Vulkan { |
|
|
|
return flags; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] VkBufferUsageFlags ImportedDescriptorAddressUsage(const Device &device) { |
|
|
|
return ImportedDescriptorUsage(device) | |
|
|
|
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
|
|
|
} |
|
|
|
|
|
|
|
// Helpers translating MemoryUsage to flags/usage
|
|
|
|
|
|
|
|
[[maybe_unused]] VkMemoryPropertyFlags MemoryUsagePropertyFlags(MemoryUsage usage) { |
|
|
|
@ -297,7 +302,16 @@ namespace Vulkan { |
|
|
|
bool HostMemoryImport::CreateDescriptorCapableWindowBuffer( |
|
|
|
const void *external_info, VkDeviceSize length, u32 external_type_bits, |
|
|
|
VkDeviceSize capacity, VkBuffer *out_buffer, u32 *out_type_mask, |
|
|
|
bool *out_descriptor_capable) const { |
|
|
|
bool *out_descriptor_capable, bool *out_address_capable, bool allow_address) const { |
|
|
|
if (allow_address && device.IsBufferDeviceAddressSupported() && |
|
|
|
TryCreateWindowBuffer(external_info, length, external_type_bits, capacity, |
|
|
|
ImportedDescriptorAddressUsage(device), out_buffer, |
|
|
|
out_type_mask)) { |
|
|
|
*out_descriptor_capable = true; |
|
|
|
*out_address_capable = true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
*out_address_capable = false; |
|
|
|
if (TryCreateWindowBuffer(external_info, length, external_type_bits, capacity, |
|
|
|
ImportedDescriptorUsage(device), out_buffer, out_type_mask)) { |
|
|
|
*out_descriptor_capable = true; |
|
|
|
@ -443,6 +457,7 @@ namespace Vulkan { |
|
|
|
window_size = hardware_buffer_window; |
|
|
|
base_offset = hardware_buffer_base; |
|
|
|
bool every_window_descriptor_capable = true; |
|
|
|
bool every_window_address_capable = true; |
|
|
|
for (size_t i = 0; i < hardware_buffers.size(); ++i) { |
|
|
|
const size_t offset = hardware_buffer_base + i * hardware_buffer_window; |
|
|
|
if (offset >= size) { |
|
|
|
@ -468,54 +483,81 @@ namespace Vulkan { |
|
|
|
.handleTypes = |
|
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, |
|
|
|
}; |
|
|
|
VkBuffer new_buffer{}; |
|
|
|
u32 type_mask = 0; |
|
|
|
Window window{}; |
|
|
|
bool descriptor_capable = false; |
|
|
|
if (!CreateDescriptorCapableWindowBuffer(&external_info, window_len, |
|
|
|
ahb_props.memoryTypeBits, |
|
|
|
ahb_props.allocationSize, &new_buffer, |
|
|
|
&type_mask, &descriptor_capable)) { |
|
|
|
break; |
|
|
|
} |
|
|
|
const auto type_index = FindImportMemoryType(memory_props, type_mask); |
|
|
|
if (!type_index) { |
|
|
|
logical.DestroyBufferRaw(new_buffer); |
|
|
|
break; |
|
|
|
} |
|
|
|
const VkImportAndroidHardwareBufferInfoANDROID import_info{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, |
|
|
|
.pNext = nullptr, |
|
|
|
.buffer = hardware_buffers[i], |
|
|
|
}; |
|
|
|
const VkMemoryDedicatedAllocateInfo dedicated_info{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, |
|
|
|
.pNext = &import_info, |
|
|
|
.image = VK_NULL_HANDLE, |
|
|
|
.buffer = new_buffer, |
|
|
|
}; |
|
|
|
const VkMemoryAllocateInfo alloc_info{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
|
|
|
.pNext = &dedicated_info, |
|
|
|
.allocationSize = ahb_props.allocationSize, |
|
|
|
.memoryTypeIndex = *type_index, |
|
|
|
bool address_capable = false; |
|
|
|
const auto build_window = [&](bool allow_address) { |
|
|
|
VkBuffer new_buffer{}; |
|
|
|
u32 type_mask = 0; |
|
|
|
if (!CreateDescriptorCapableWindowBuffer(&external_info, window_len, |
|
|
|
ahb_props.memoryTypeBits, |
|
|
|
ahb_props.allocationSize, &new_buffer, |
|
|
|
&type_mask, &descriptor_capable, |
|
|
|
&address_capable, allow_address)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
const auto type_index = FindImportMemoryType(memory_props, type_mask); |
|
|
|
if (!type_index) { |
|
|
|
logical.DestroyBufferRaw(new_buffer); |
|
|
|
return false; |
|
|
|
} |
|
|
|
const VkImportAndroidHardwareBufferInfoANDROID import_info{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, |
|
|
|
.pNext = nullptr, |
|
|
|
.buffer = hardware_buffers[i], |
|
|
|
}; |
|
|
|
const VkMemoryDedicatedAllocateInfo dedicated_info{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, |
|
|
|
.pNext = &import_info, |
|
|
|
.image = VK_NULL_HANDLE, |
|
|
|
.buffer = new_buffer, |
|
|
|
}; |
|
|
|
const VkMemoryAllocateFlagsInfo flags_info{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, |
|
|
|
.pNext = &dedicated_info, |
|
|
|
.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, |
|
|
|
.deviceMask = 0, |
|
|
|
}; |
|
|
|
const VkMemoryAllocateInfo alloc_info{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
|
|
|
.pNext = address_capable ? static_cast<const void *>(&flags_info) |
|
|
|
: static_cast<const void *>(&dedicated_info), |
|
|
|
.allocationSize = ahb_props.allocationSize, |
|
|
|
.memoryTypeIndex = *type_index, |
|
|
|
}; |
|
|
|
vk::DeviceMemory memory = logical.TryAllocateMemory(alloc_info); |
|
|
|
if (!memory) { |
|
|
|
logical.DestroyBufferRaw(new_buffer); |
|
|
|
return false; |
|
|
|
} |
|
|
|
if (logical.BindBufferMemory(new_buffer, *memory, 0) != VK_SUCCESS) { |
|
|
|
logical.DestroyBufferRaw(new_buffer); |
|
|
|
return false; |
|
|
|
} |
|
|
|
VkDeviceAddress address = 0; |
|
|
|
if (address_capable) { |
|
|
|
address = logical.GetBufferDeviceAddress(new_buffer); |
|
|
|
if (address == 0) { |
|
|
|
address_capable = false; |
|
|
|
} |
|
|
|
} |
|
|
|
window = Window{ |
|
|
|
.memory = std::move(memory), |
|
|
|
.buffer = new_buffer, |
|
|
|
.address = address, |
|
|
|
}; |
|
|
|
return true; |
|
|
|
}; |
|
|
|
vk::DeviceMemory memory = logical.TryAllocateMemory(alloc_info); |
|
|
|
if (!memory) { |
|
|
|
logical.DestroyBufferRaw(new_buffer); |
|
|
|
break; |
|
|
|
} |
|
|
|
if (logical.BindBufferMemory(new_buffer, *memory, 0) != VK_SUCCESS) { |
|
|
|
logical.DestroyBufferRaw(new_buffer); |
|
|
|
if (!build_window(true) && !build_window(false)) { |
|
|
|
break; |
|
|
|
} |
|
|
|
windows.push_back(Window{ |
|
|
|
.memory = std::move(memory), |
|
|
|
.buffer = new_buffer, |
|
|
|
}); |
|
|
|
windows.push_back(std::move(window)); |
|
|
|
every_window_descriptor_capable &= descriptor_capable; |
|
|
|
every_window_address_capable &= address_capable; |
|
|
|
imported_size += static_cast<size_t>(window_len); |
|
|
|
} |
|
|
|
direct_descriptors = !windows.empty() && every_window_descriptor_capable; |
|
|
|
direct_addresses = direct_descriptors && every_window_address_capable; |
|
|
|
if (windows.empty()) { |
|
|
|
window_size = 0; |
|
|
|
base_offset = 0; |
|
|
|
|