Files
DroidDeck/app/src/main/cpp/framegen/lsfg/lsfg_probe.cpp
T
2026-10-13 21:27:42 -04:00

150 lines
5.8 KiB
C++

#include "lsfg_probe.h"
#include "../VulkanRendererContext.h"
#include <cstdio>
#include <cstring>
namespace lsfg {
namespace {
bool hasExtension(const std::vector<VkExtensionProperties>& exts, const char* name) {
for (const auto& e : exts)
if (strcmp(e.extensionName, name) == 0) return true;
return false;
}
}
FeatureSupport queryFeatures(const VkTable& vk, VkPhysicalDevice pd,
const std::vector<VkExtensionProperties>& deviceExtensions,
bool allowVk11) {
FeatureSupport fs{};
if (pd == VK_NULL_HANDLE || !vk.GetPhysicalDeviceProperties) return fs;
VkPhysicalDeviceProperties props{};
vk.GetPhysicalDeviceProperties(pd, &props);
fs.deviceApiVersion = props.apiVersion;
fs.apiAtLeast13 = props.apiVersion >= VK_API_VERSION_1_3;
if (!vk.GetPhysicalDeviceFeatures2) return fs;
const bool below12 = props.apiVersion < VK_API_VERSION_1_2;
if (below12) {
if (!allowVk11) return fs;
fs.hasSpirv14 = hasExtension(deviceExtensions, VK_KHR_SPIRV_1_4_EXTENSION_NAME);
fs.hasFloatControls = hasExtension(deviceExtensions, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
fs.hasMemoryModelExt = hasExtension(deviceExtensions, VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME);
if (!fs.hasSpirv14 || !fs.hasFloatControls || !fs.hasMemoryModelExt) {
fs.queried = true;
return fs;
}
fs.extensionPath = true;
fs.spirvTarget = kSpirv14;
} else if (!fs.apiAtLeast13 && allowVk11) {
fs.extensionPath = true;
fs.spirvTarget = kSpirv15;
}
VkPhysicalDeviceVulkan12Features v12{};
v12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
VkPhysicalDeviceVulkanMemoryModelFeaturesKHR mm{};
mm.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR;
VkPhysicalDeviceFeatures2 f2{};
f2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
f2.pNext = below12 ? (void*)&mm : (void*)&v12;
vk.GetPhysicalDeviceFeatures2(pd, &f2);
fs.queried = true;
if (below12) {
fs.vulkanMemoryModel = mm.vulkanMemoryModel == VK_TRUE;
fs.vulkanMemoryModelDeviceScope = mm.vulkanMemoryModelDeviceScope == VK_TRUE;
} else {
fs.vulkanMemoryModel = v12.vulkanMemoryModel == VK_TRUE;
fs.vulkanMemoryModelDeviceScope = v12.vulkanMemoryModelDeviceScope == VK_TRUE;
}
fs.storageImageWriteWithoutFormat = f2.features.shaderStorageImageWriteWithoutFormat == VK_TRUE;
fs.storageImageExtendedFormats = f2.features.shaderStorageImageExtendedFormats == VK_TRUE;
return fs;
}
std::vector<const char*> extensionNames(const FeatureSupport& f) {
std::vector<const char*> out;
if (!f.extensionPath || f.deviceApiVersion >= VK_API_VERSION_1_2) return out;
out.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
out.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
out.push_back(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME);
return out;
}
bool probeLinearBlit(const VkTable& vk, VkPhysicalDevice pd, VkFormat fmt) {
if (pd == VK_NULL_HANDLE || fmt == VK_FORMAT_UNDEFINED
|| !vk.GetPhysicalDeviceFormatProperties) return false;
VkFormatProperties fp{};
vk.GetPhysicalDeviceFormatProperties(pd, fmt, &fp);
return (fp.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) != 0;
}
bool probeStorageFormat(const VkTable& vk, VkPhysicalDevice pd, VkFormat fmt) {
if (pd == VK_NULL_HANDLE || fmt == VK_FORMAT_UNDEFINED
|| !vk.GetPhysicalDeviceFormatProperties) return false;
VkFormatProperties fp{};
vk.GetPhysicalDeviceFormatProperties(pd, fmt, &fp);
const VkFormatFeatureFlags need =
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
| VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
| VK_FORMAT_FEATURE_BLIT_DST_BIT;
return (fp.optimalTilingFeatures & need) == need;
}
void explain(Caps& caps) {
const FeatureSupport& f = caps.features;
const char* why = nullptr;
if (!f.queried) {
why = f.deviceApiVersion < VK_API_VERSION_1_2
? "device Vulkan version below 1.2"
: "vkGetPhysicalDeviceFeatures2 unavailable";
} else if (!f.apiAtLeast13 && !f.extensionPath) {
if (f.deviceApiVersion < VK_API_VERSION_1_2) {
why = !f.hasSpirv14 ? "Vulkan 1.1 driver lacks VK_KHR_spirv_1_4"
: !f.hasFloatControls ? "Vulkan 1.1 driver lacks VK_KHR_shader_float_controls"
: "Vulkan 1.1 driver lacks VK_KHR_vulkan_memory_model";
} else {
why = "device Vulkan version below 1.3 (SPIR-V 1.6 will not load)";
}
} else if (!f.vulkanMemoryModel) {
why = "driver lacks vulkanMemoryModel";
} else if (!f.storageImageWriteWithoutFormat) {
why = "driver lacks shaderStorageImageWriteWithoutFormat";
} else if (!f.storageImageExtendedFormats) {
why = "driver lacks shaderStorageImageExtendedFormats";
} else if (!caps.featuresEnabled) {
why = "required features not enabled at device creation";
} else if (!caps.storageOnSwapchainFormat) {
why = "swapchain format is not storage-image capable";
}
if (why) {
snprintf(caps.reason, sizeof(caps.reason), "unsupported: %s", why);
} else {
snprintf(caps.reason, sizeof(caps.reason),
"supported (device Vulkan %u.%u.%u%s, fmt %d)",
VK_VERSION_MAJOR(f.deviceApiVersion),
VK_VERSION_MINOR(f.deviceApiVersion),
VK_VERSION_PATCH(f.deviceApiVersion),
f.extensionPath ? " via extensions, SPIR-V lowered" : "",
(int)caps.probedFormat);
}
}
}