update parallel rdp

This commit is contained in:
Logan McNaughton committed 2022-05-29 18:33:47 -06:00
1 parent 37f61aef57
commit b96f789d1a
108 files changed
+58317 -109283

No files matched your search

+234 -129
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2017-2020 Hans-Kristian Arntzen
/* Copyright (c) 2017-2022 Hans-Kristian Arntzen
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -124,18 +124,18 @@ Semaphore Device::request_external_semaphore(VkSemaphore semaphore, bool signall
}
#ifndef _WIN32
Semaphore Device::request_imported_semaphore(int fd, VkExternalSemaphoreHandleTypeFlagBitsKHR handle_type)
Semaphore Device::request_imported_semaphore(int fd, VkExternalSemaphoreHandleTypeFlagBits handle_type)
{
LOCK();
if (!ext.supports_external)
return {};
VkExternalSemaphorePropertiesKHR props = { VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR };
VkPhysicalDeviceExternalSemaphoreInfoKHR info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR };
VkExternalSemaphoreProperties props = { VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES };
VkPhysicalDeviceExternalSemaphoreInfo info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO };
info.handleType = handle_type;
vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(gpu, &info, &props);
if ((props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
vkGetPhysicalDeviceExternalSemaphoreProperties(gpu, &info, &props);
if ((props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
return Semaphore(nullptr);
auto semaphore = managers.semaphore.request_cleared_semaphore();
@@ -144,7 +144,7 @@ Semaphore Device::request_imported_semaphore(int fd, VkExternalSemaphoreHandleTy
import.fd = fd;
import.semaphore = semaphore;
import.handleType = handle_type;
import.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR;
import.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
Semaphore ptr(handle_pool.semaphores.allocate(this, semaphore, false));
if (table->vkImportSemaphoreFdKHR(device, &import) != VK_SUCCESS)
@@ -303,11 +303,7 @@ Shader *Device::request_shader(const uint32_t *data, size_t size,
const ResourceLayout *layout,
const ImmutableSamplerBank *sampler_bank)
{
Util::Hasher hasher;
hasher.data(data, size);
ImmutableSamplerBank::hash(hasher, sampler_bank);
auto hash = hasher.get();
auto hash = Shader::hash(data, size, sampler_bank);
auto *ret = shaders.find(hash);
if (!ret)
ret = shaders.emplace_yield(hash, hash, this, data, size, layout, sampler_bank);
@@ -446,7 +442,8 @@ void Device::bake_program(Program &program)
layout.sets[set].storage_image_mask |= shader_layout.sets[set].storage_image_mask;
layout.sets[set].uniform_buffer_mask |= shader_layout.sets[set].uniform_buffer_mask;
layout.sets[set].storage_buffer_mask |= shader_layout.sets[set].storage_buffer_mask;
layout.sets[set].sampled_buffer_mask |= shader_layout.sets[set].sampled_buffer_mask;
layout.sets[set].sampled_texel_buffer_mask |= shader_layout.sets[set].sampled_texel_buffer_mask;
layout.sets[set].storage_texel_buffer_mask |= shader_layout.sets[set].storage_texel_buffer_mask;
layout.sets[set].input_attachment_mask |= shader_layout.sets[set].input_attachment_mask;
layout.sets[set].sampler_mask |= shader_layout.sets[set].sampler_mask;
layout.sets[set].separate_image_mask |= shader_layout.sets[set].separate_image_mask;
@@ -473,7 +470,8 @@ void Device::bake_program(Program &program)
shader_layout.sets[set].storage_image_mask |
shader_layout.sets[set].uniform_buffer_mask|
shader_layout.sets[set].storage_buffer_mask |
shader_layout.sets[set].sampled_buffer_mask |
shader_layout.sets[set].sampled_texel_buffer_mask |
shader_layout.sets[set].storage_texel_buffer_mask |
shader_layout.sets[set].input_attachment_mask |
shader_layout.sets[set].sampler_mask |
shader_layout.sets[set].separate_image_mask;
@@ -556,9 +554,10 @@ void Device::bake_program(Program &program)
bool Device::init_pipeline_cache(const uint8_t *data, size_t size)
{
static const auto uuid_size = sizeof(gpu_props.pipelineCacheUUID);
static const auto hash_size = sizeof(Util::Hash);
VkPipelineCacheCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO };
if (!data || size < uuid_size)
if (!data || size < uuid_size + hash_size)
{
LOGI("Creating a fresh pipeline cache.\n");
}
@@ -568,9 +567,24 @@ bool Device::init_pipeline_cache(const uint8_t *data, size_t size)
}
else
{
info.initialDataSize = size - uuid_size;
info.pInitialData = data + uuid_size;
LOGI("Initializing pipeline cache.\n");
Util::Hash reference_hash;
memcpy(&reference_hash, data + uuid_size, sizeof(reference_hash));
info.initialDataSize = size - uuid_size - hash_size;
data += uuid_size + hash_size;
info.pInitialData = data;
Util::Hasher h;
h.data(data, info.initialDataSize);
if (h.get() == reference_hash)
LOGI("Initializing pipeline cache.\n");
else
{
LOGW("Pipeline cache is corrupt, creating a fresh cache.\n");
info.pInitialData = nullptr;
info.initialDataSize = 0;
}
}
if (pipeline_cache != VK_NULL_HANDLE)
@@ -579,35 +593,12 @@ bool Device::init_pipeline_cache(const uint8_t *data, size_t size)
return table->vkCreatePipelineCache(device, &info, nullptr, &pipeline_cache) == VK_SUCCESS;
}
static inline char to_hex(uint8_t v)
{
if (v < 10)
return char('0' + v);
else
return char('a' + (v - 10));
}
string Device::get_pipeline_cache_string() const
{
string res;
res.reserve(sizeof(gpu_props.pipelineCacheUUID) * 2);
for (auto &c : gpu_props.pipelineCacheUUID)
{
res += to_hex(uint8_t((c >> 4) & 0xf));
res += to_hex(uint8_t(c & 0xf));
}
return res;
}
void Device::init_pipeline_cache()
{
#ifdef GRANITE_VULKAN_FILESYSTEM
if (!system_handles.filesystem)
return;
auto file = system_handles.filesystem->open(Util::join("cache://pipeline_cache_", get_pipeline_cache_string(), ".bin"),
Granite::FileMode::ReadOnly);
auto file = system_handles.filesystem->open("cache://pipeline_cache.bin", Granite::FileMode::ReadOnly);
if (file)
{
auto size = file->get_size();
@@ -626,6 +617,7 @@ size_t Device::get_pipeline_cache_size()
return 0;
static const auto uuid_size = sizeof(gpu_props.pipelineCacheUUID);
static const auto hash_size = sizeof(Util::Hash);
size_t size = 0;
if (table->vkGetPipelineCacheData(device, pipeline_cache, &size, nullptr) != VK_SUCCESS)
{
@@ -633,7 +625,7 @@ size_t Device::get_pipeline_cache_size()
return 0;
}
return size + uuid_size;
return size + uuid_size + hash_size;
}
bool Device::get_pipeline_cache_data(uint8_t *data, size_t size)
@@ -642,12 +634,15 @@ bool Device::get_pipeline_cache_data(uint8_t *data, size_t size)
return false;
static const auto uuid_size = sizeof(gpu_props.pipelineCacheUUID);
if (size < uuid_size)
static const auto hash_size = sizeof(Util::Hash);
if (size < uuid_size + hash_size)
return false;
size -= uuid_size;
auto *hash_data = data + uuid_size;
size -= uuid_size + hash_size;
memcpy(data, gpu_props.pipelineCacheUUID, uuid_size);
data += uuid_size;
data = hash_data + hash_size;
if (table->vkGetPipelineCacheData(device, pipeline_cache, &size, data) != VK_SUCCESS)
{
@@ -655,6 +650,11 @@ bool Device::get_pipeline_cache_data(uint8_t *data, size_t size)
return false;
}
Util::Hasher h;
h.data(data, size);
auto blob_hash = h.get();
memcpy(hash_data, &blob_hash, sizeof(blob_hash));
return true;
}
@@ -671,8 +671,10 @@ void Device::flush_pipeline_cache()
return;
}
auto file = system_handles.filesystem->open(Util::join("cache://pipeline_cache_", get_pipeline_cache_string(), ".bin"),
Granite::FileMode::WriteOnly);
auto file = system_handles.filesystem->open(
"cache://pipeline_cache.bin",
Granite::FileMode::WriteOnlyTransactional);
if (!file)
{
LOGE("Failed to get pipeline cache data.\n");
@@ -700,36 +702,16 @@ void Device::init_workarounds()
#ifdef __APPLE__
// Events are not supported in MoltenVK.
// TODO: Use VK_KHR_portability_subset to determine this.
workarounds.emulate_event_as_pipeline_barrier = true;
LOGW("Emulating events as pipeline barriers on Metal emulation.\n");
#else
if (gpu_props.vendorID == VENDOR_ID_NVIDIA &&
#ifdef _WIN32
VK_VERSION_MAJOR(gpu_props.driverVersion) < 417)
#else
VK_VERSION_MAJOR(gpu_props.driverVersion) < 415)
#endif
{
workarounds.force_store_in_render_pass = true;
LOGW("Detected workaround for render pass STORE_OP_STORE.\n");
}
if (gpu_props.vendorID == VENDOR_ID_QCOM)
{
// Apparently, we need to use STORE_OP_STORE in all render passes no matter what ...
workarounds.force_store_in_render_pass = true;
workarounds.broken_color_write_mask = true;
LOGW("Detected workaround for render pass STORE_OP_STORE.\n");
LOGW("Detected workaround for broken color write masks.\n");
}
// UNDEFINED -> COLOR_ATTACHMENT_OPTIMAL stalls, so need to acquire async.
if (gpu_props.vendorID == VENDOR_ID_ARM)
{
LOGW("Workaround applied: Emulating events as pipeline barriers.\n");
LOGW("Workaround applied: Optimize ALL_GRAPHICS_BIT barriers.\n");
// All performance related workarounds.
// Both are performance related workarounds.
workarounds.emulate_event_as_pipeline_barrier = true;
workarounds.optimize_all_graphics_barrier = true;
@@ -759,6 +741,7 @@ void Device::set_context(const Context &context)
mem_props = context.get_mem_props();
gpu_props = context.get_gpu_props();
ext = context.get_enabled_device_features();
system_handles = context.get_system_handles();
init_workarounds();
@@ -814,14 +797,14 @@ void Device::set_context(const Context &context)
queue_data[i].performance_query_pool.init_device(this, queue_info.family_indices[i]);
}
#ifdef GRANITE_VULKAN_FOSSILIZE
init_pipeline_state();
#endif
#ifdef GRANITE_VULKAN_FILESYSTEM
init_shader_manager_cache();
#endif
system_handles = context.get_system_handles();
#ifdef GRANITE_VULKAN_FOSSILIZE
init_pipeline_state(context.get_feature_filter());
#endif
if (system_handles.timeline_trace_file)
init_calibrated_timestamps();
}
@@ -2997,20 +2980,18 @@ public:
bool setup_view_usage_info(VkImageViewCreateInfo &create_info, VkImageUsageFlags usage,
VkImageViewUsageCreateInfo &usage_info) const
{
if (device->get_device_features().supports_maintenance_2)
{
usage_info.usage = usage;
usage_info.usage &= VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
usage_info.usage = usage;
usage_info.usage &= VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
vk_video_image_usage_flags;
if (format_is_srgb(create_info.format))
usage_info.usage &= ~VK_IMAGE_USAGE_STORAGE_BIT;
if (format_is_srgb(create_info.format))
usage_info.usage &= ~VK_IMAGE_USAGE_STORAGE_BIT;
usage_info.pNext = create_info.pNext;
create_info.pNext = &usage_info;
}
usage_info.pNext = create_info.pNext;
create_info.pNext = &usage_info;
return true;
}
@@ -3276,7 +3257,7 @@ ImageViewHandle Device::create_image_view(const ImageViewCreateInfo &create_info
#ifndef _WIN32
ImageHandle Device::create_imported_image(int fd, VkDeviceSize size, uint32_t memory_type,
VkExternalMemoryHandleTypeFlagBitsKHR handle_type,
VkExternalMemoryHandleTypeFlagBits handle_type,
const ImageCreateInfo &create_info)
{
if (!ext.supports_external)
@@ -3301,7 +3282,7 @@ ImageHandle Device::create_imported_image(int fd, VkDeviceSize size, uint32_t me
info.pNext = create_info.pnext;
VK_ASSERT(create_info.domain != ImageDomain::Transient);
VkExternalMemoryImageCreateInfoKHR externalInfo = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR };
VkExternalMemoryImageCreateInfo externalInfo = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO };
externalInfo.handleTypes = handle_type;
externalInfo.pNext = info.pNext;
info.pNext = &externalInfo;
@@ -3315,7 +3296,7 @@ ImageHandle Device::create_imported_image(int fd, VkDeviceSize size, uint32_t me
alloc_info.allocationSize = size;
alloc_info.memoryTypeIndex = memory_type;
VkMemoryDedicatedAllocateInfoKHR dedicated_info = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };
VkMemoryDedicatedAllocateInfo dedicated_info = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO };
dedicated_info.image = holder.image;
alloc_info.pNext = &dedicated_info;
@@ -3537,24 +3518,21 @@ bool Device::allocate_image_memory(DeviceAllocation *allocation, const ImageCrea
}
else
{
if (!ext.supports_bind_memory2 || !ext.supports_get_memory_requirements2)
return false;
VkBindImageMemoryInfo bind_infos[3];
VkBindImagePlaneMemoryInfo bind_plane_infos[3];
VK_ASSERT(num_planes <= 3);
for (unsigned plane = 0; plane < num_planes; plane++)
{
VkMemoryRequirements2KHR memory_req = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
VkImageMemoryRequirementsInfo2KHR image_info = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR };
VkMemoryRequirements2 memory_req = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 };
VkImageMemoryRequirementsInfo2 image_info = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 };
image_info.image = image;
VkImagePlaneMemoryRequirementsInfo plane_info = { VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR };
VkImagePlaneMemoryRequirementsInfo plane_info = { VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO };
plane_info.planeAspect = static_cast<VkImageAspectFlagBits>(VK_IMAGE_ASPECT_PLANE_0_BIT << plane);
image_info.pNext = &plane_info;
table->vkGetImageMemoryRequirements2KHR(device, &image_info, &memory_req);
table->vkGetImageMemoryRequirements2(device, &image_info, &memory_req);
auto &reqs = memory_req.memoryRequirements;
auto &alias = *info.memory_aliases[plane];
@@ -3576,7 +3554,7 @@ bool Device::allocate_image_memory(DeviceAllocation *allocation, const ImageCrea
bind_plane_infos[plane].planeAspect = static_cast<VkImageAspectFlagBits>(VK_IMAGE_ASPECT_PLANE_0_BIT << plane);
}
if (table->vkBindImageMemory2KHR(device, num_planes, bind_infos) != VK_SUCCESS)
if (table->vkBindImageMemory2(device, num_planes, bind_infos) != VK_SUCCESS)
return false;
}
}
@@ -3773,15 +3751,15 @@ ImageHandle Device::create_image_from_staging_buffer(const ImageCreateInfo &crea
if (info.samples != VK_SAMPLE_COUNT_1_BIT)
return ImageHandle(nullptr);
VkImageFormatProperties props;
VkImageFormatProperties2 props = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 };
if (!get_image_format_properties(info.format, info.imageType, info.tiling, info.usage, info.flags, &props))
return ImageHandle(nullptr);
if (!props.maxArrayLayers ||
!props.maxMipLevels ||
(info.extent.width > props.maxExtent.width) ||
(info.extent.height > props.maxExtent.height) ||
(info.extent.depth > props.maxExtent.depth))
if (!props.imageFormatProperties.maxArrayLayers ||
!props.imageFormatProperties.maxMipLevels ||
(info.extent.width > props.imageFormatProperties.maxExtent.width) ||
(info.extent.height > props.imageFormatProperties.maxExtent.height) ||
(info.extent.depth > props.imageFormatProperties.maxExtent.depth))
{
return ImageHandle(nullptr);
}
@@ -4146,7 +4124,7 @@ BufferHandle Device::create_imported_host_buffer(const BufferCreateInfo &create_
return BufferHandle{};
}
VkExternalMemoryBufferCreateInfo external_info = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR };
VkExternalMemoryBufferCreateInfo external_info = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO };
external_info.handleTypes = type;
VkMemoryHostPointerPropertiesEXT host_pointer_props = { VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT };
@@ -4289,26 +4267,28 @@ BufferHandle Device::create_buffer(const BufferCreateInfo &create_info, const vo
if (!managers.memory.allocate(reqs.size, reqs.alignment, mode, memory_type, &allocation))
{
auto fallback_domain = create_info.domain;
// This memory type is rather scarce, so fallback to Host type if we've exhausted this memory.
if (create_info.domain == BufferDomain::LinkedDeviceHost)
{
LOGW("Exhausted LinkedDeviceHost memory, falling back to host.\n");
memory_type = find_memory_type(BufferDomain::Host, reqs.memoryTypeBits);
if (memory_type == UINT32_MAX)
{
LOGE("Failed to find memory type.\n");
table->vkDestroyBuffer(device, buffer, nullptr);
return BufferHandle(nullptr);
}
fallback_domain = BufferDomain::Host;
if (!managers.memory.allocate(reqs.size, reqs.alignment, mode, memory_type, &allocation))
{
table->vkDestroyBuffer(device, buffer, nullptr);
return BufferHandle(nullptr);
}
}
else
else if (create_info.domain == BufferDomain::LinkedDeviceHostPreferDevice)
{
LOGW("Exhausted LinkedDeviceHostPreferDevice memory, falling back to device.\n");
fallback_domain = BufferDomain::Device;
}
memory_type = find_memory_type(fallback_domain, reqs.memoryTypeBits);
if (memory_type == UINT32_MAX ||
fallback_domain == create_info.domain ||
!managers.memory.allocate(reqs.size, reqs.alignment, mode, memory_type, &allocation))
{
LOGE("Failed to allocate fallback memory.\n");
table->vkDestroyBuffer(device, buffer, nullptr);
return BufferHandle(nullptr);
}
@@ -4376,25 +4356,70 @@ bool Device::memory_type_is_host_visible(uint32_t type) const
return (mem_props.memoryTypes[type].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
}
void Device::get_format_properties(VkFormat format, VkFormatProperties *properties)
static VkFormatFeatureFlags2KHR promote_storage_usage(const DeviceFeatures &features, VkFormat format,
VkFormatFeatureFlags2KHR supported)
{
vkGetPhysicalDeviceFormatProperties(gpu, format, properties);
if ((supported & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR) != 0 &&
format_supports_storage_image_read_write_without_format(format))
{
if (features.enabled_features.shaderStorageImageReadWithoutFormat)
supported |= VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR;
if (features.enabled_features.shaderStorageImageWriteWithoutFormat)
supported |= VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR;
}
return supported;
}
void Device::get_format_properties(VkFormat format, VkFormatProperties3KHR *properties3) const
{
VkFormatProperties2 properties2 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 };
VK_ASSERT(properties3->sType == VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR);
if (ext.supports_format_feature_flags2)
{
properties2.pNext = properties3;
vkGetPhysicalDeviceFormatProperties2(gpu, format, &properties2);
}
else
{
// Skip properties3 and synthesize the results instead.
properties2.pNext = properties3->pNext;
vkGetPhysicalDeviceFormatProperties2(gpu, format, &properties2);
properties3->optimalTilingFeatures = properties2.formatProperties.optimalTilingFeatures;
properties3->linearTilingFeatures = properties2.formatProperties.linearTilingFeatures;
properties3->bufferFeatures = properties2.formatProperties.bufferFeatures;
// Automatically promote for supported formats.
properties3->optimalTilingFeatures =
promote_storage_usage(ext, format, properties3->optimalTilingFeatures);
properties3->linearTilingFeatures =
promote_storage_usage(ext, format, properties3->linearTilingFeatures);
}
}
bool Device::get_image_format_properties(VkFormat format, VkImageType type, VkImageTiling tiling,
VkImageUsageFlags usage, VkImageCreateFlags flags,
VkImageFormatProperties *properties)
VkImageFormatProperties2 *properties2) const
{
auto res = vkGetPhysicalDeviceImageFormatProperties(gpu, format, type, tiling, usage, flags,
properties);
VK_ASSERT(properties2->sType == VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2);
VkPhysicalDeviceImageFormatInfo2 info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 };
info.format = format;
info.type = type;
info.tiling = tiling;
info.usage = usage;
info.flags = flags;
VkResult res = vkGetPhysicalDeviceImageFormatProperties2(gpu, &info, properties2);
return res == VK_SUCCESS;
}
bool Device::image_format_is_supported(VkFormat format, VkFormatFeatureFlags required, VkImageTiling tiling) const
bool Device::image_format_is_supported(VkFormat format, VkFormatFeatureFlags2KHR required, VkImageTiling tiling) const
{
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(gpu, format, &props);
auto flags = tiling == VK_IMAGE_TILING_OPTIMAL ? props.optimalTilingFeatures : props.linearTilingFeatures;
VkFormatProperties3KHR props3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR };
get_format_properties(format, &props3);
auto flags = tiling == VK_IMAGE_TILING_OPTIMAL ? props3.optimalTilingFeatures : props3.linearTilingFeatures;
return (flags & required) == required;
}
@@ -4817,9 +4842,8 @@ ShaderManager &Device::get_shader_manager()
#ifdef GRANITE_VULKAN_FILESYSTEM
void Device::init_shader_manager_cache()
{
//if (!shader_manager.load_shader_cache("assets://shader_cache.json"))
// shader_manager.load_shader_cache("cache://shader_cache.json");
shader_manager.load_shader_cache("assets://shader_cache.json");
if (!shader_manager.load_shader_cache("assets://shader_cache.json"))
shader_manager.load_shader_cache("cache://shader_cache.json");
}
void Device::flush_shader_manager_cache()
@@ -4881,6 +4905,87 @@ bool Device::supports_subgroup_size_log2(bool subgroup_full_group, uint8_t subgr
return (ext.subgroup_size_control_properties.requiredSubgroupSizeStages & VK_SHADER_STAGE_COMPUTE_BIT) != 0;
}
const QueueInfo &Device::get_queue_info() const
{
return queue_info;
}
void Device::timestamp_log_reset()
{
managers.timestamps.reset();
}
void Device::timestamp_log(const TimestampIntervalReportCallback &cb) const
{
managers.timestamps.log_simple(cb);
}
CommandBufferHandle request_command_buffer_with_ownership_transfer(
Device &device,
const Vulkan::Image &image,
const OwnershipTransferInfo &info,
const Vulkan::Semaphore &semaphore)
{
auto &queue_info = device.get_queue_info();
unsigned old_family = queue_info.family_indices[device.get_physical_queue_type(info.old_queue)];
unsigned new_family = queue_info.family_indices[device.get_physical_queue_type(info.new_queue)];
bool image_is_concurrent = (image.get_create_info().misc &
(Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT |
Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT |
Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT |
Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_GRAPHICS_BIT)) != 0;
bool need_ownership_transfer = old_family != new_family && !image_is_concurrent;
VkImageMemoryBarrier ownership = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
ownership.image = image.get_image();
ownership.srcAccessMask = 0;
ownership.dstAccessMask = 0;
ownership.subresourceRange.aspectMask = format_to_aspect_mask(image.get_format());
ownership.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
ownership.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
ownership.oldLayout = info.old_image_layout;
ownership.newLayout = info.new_image_layout;
if (need_ownership_transfer)
{
ownership.srcQueueFamilyIndex = old_family;
ownership.dstQueueFamilyIndex = new_family;
if (semaphore)
device.add_wait_semaphore(info.old_queue, semaphore, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, true);
auto release_cmd = device.request_command_buffer(info.old_queue);
release_cmd->image_barriers(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1, &ownership);
Semaphore sem;
device.submit(release_cmd, nullptr, 1, &sem);
device.add_wait_semaphore(info.new_queue, sem, info.dst_pipeline_stage, true);
}
else
{
ownership.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
ownership.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
if (semaphore)
device.add_wait_semaphore(info.new_queue, semaphore, info.dst_pipeline_stage, true);
}
// Ownership transfers may perform writes, so make those operations visible.
// If we require neither layout transition nor ownership transfer,
// visibility is ensured by semaphores.
bool need_dst_barrier = need_ownership_transfer || info.old_image_layout != info.new_image_layout;
auto acquire_cmd = device.request_command_buffer(info.new_queue);
if (need_dst_barrier)
{
ownership.dstAccessMask = info.dst_access;
acquire_cmd->image_barriers(info.dst_pipeline_stage, info.dst_pipeline_stage, 1, &ownership);
}
return acquire_cmd;
}
static ImplementationQuirks implementation_quirks;
ImplementationQuirks &ImplementationQuirks::get()
{