iwa/source/util/vkutil.cpp
2024-04-06 14:11:26 +02:00

276 lines
8.3 KiB
C++

#include "iwa/util/vkutil.hpp"
#include "iwa/device.hpp"
#include "iwa/log.hpp"
namespace iwa
{
unsigned vkFormatSize(vk::Format format) noexcept
{
switch (format)
{
// 8 bit integer
case vk::Format::eR8Uint:
case vk::Format::eR8Sint:
case vk::Format::eR8Unorm:
case vk::Format::eR8Srgb:
return 1;
case vk::Format::eR8G8Uint:
case vk::Format::eR8G8Sint:
case vk::Format::eR8G8Unorm:
case vk::Format::eR8G8Srgb:
return 2;
case vk::Format::eR8G8B8Uint:
case vk::Format::eR8G8B8Sint:
case vk::Format::eR8G8B8Unorm:
case vk::Format::eR8G8B8Srgb:
return 3;
case vk::Format::eR8G8B8A8Uint:
case vk::Format::eR8G8B8A8Sint:
case vk::Format::eR8G8B8A8Unorm:
case vk::Format::eR8G8B8A8Srgb:
return 4;
// 16 bit integer
case vk::Format::eR16Uint:
case vk::Format::eR16Sint:
case vk::Format::eR16Unorm:
return 2;
case vk::Format::eR16G16Uint:
case vk::Format::eR16G16Sint:
case vk::Format::eR16G16Unorm:
return 4;
case vk::Format::eR16G16B16Uint:
case vk::Format::eR16G16B16Sint:
case vk::Format::eR16G16B16Unorm:
return 6;
case vk::Format::eR16G16B16A16Uint:
case vk::Format::eR16G16B16A16Sint:
case vk::Format::eR16G16B16A16Unorm:
return 8;
// 32 bit integer
case vk::Format::eR32Uint:
case vk::Format::eR32Sint:
return 4;
case vk::Format::eR32G32Uint:
case vk::Format::eR32G32Sint:
return 8;
case vk::Format::eR32G32B32Uint:
case vk::Format::eR32G32B32Sint:
return 12;
case vk::Format::eR32G32B32A32Uint:
case vk::Format::eR32G32B32A32Sint:
return 16;
// 64 bit integer
case vk::Format::eR64Uint:
case vk::Format::eR64Sint:
return 8;
case vk::Format::eR64G64Uint:
case vk::Format::eR64G64Sint:
return 16;
case vk::Format::eR64G64B64Uint:
case vk::Format::eR64G64B64Sint:
return 24;
case vk::Format::eR64G64B64A64Uint:
case vk::Format::eR64G64B64A64Sint:
return 32;
// 16 bit float
case vk::Format::eR16Sfloat:
return 2;
case vk::Format::eR16G16Sfloat:
return 4;
case vk::Format::eR16G16B16Sfloat:
return 6;
case vk::Format::eR16G16B16A16Sfloat:
return 8;
// 32 bit float
case vk::Format::eR32Sfloat:
return 4;
case vk::Format::eR32G32Sfloat:
return 8;
case vk::Format::eR32G32B32Sfloat:
return 12;
case vk::Format::eR32G32B32A32Sfloat:
return 16;
// 64 bit float
case vk::Format::eR64Sfloat:
return 8;
case vk::Format::eR64G64Sfloat:
return 16;
case vk::Format::eR64G64B64Sfloat:
return 24;
case vk::Format::eR64G64B64A64Sfloat:
return 32;
default:
logAndDie("I've never seen this format :(");
}
}
unsigned vkIndexTypeSize(vk::IndexType indexType) noexcept
{
switch (indexType)
{
case vk::IndexType::eNoneKHR:
return 0;
case vk::IndexType::eUint8EXT:
return 1;
case vk::IndexType::eUint16:
return 2;
case vk::IndexType::eUint32:
return 4;
default:
logAndDie("What is this sorcery?");
}
}
bool isDepthFormat(vk::Format format) noexcept
{
for (const vk::Format depthFormat : DEPTH_FORMATS) {
if (format == depthFormat) {
return true;
}
}
return false;
}
bool isStencilFormat(vk::Format format) noexcept
{
for (const vk::Format stencilFormat : STENCIL_FORMATS) {
if (format == stencilFormat) {
return true;
}
}
return false;
}
#if 0
std::string formatVkVariant(const VkVariantMWN& variant)
{
switch (variant.type)
{
case VK_VARIANT_TYPE_UNKNOWN_MWN:
return "???";
case VK_VARIANT_TYPE_NONE_MWN:
return "<none>";
case VK_VARIANT_TYPE_BOOL_MWN:
return variant.uintValue ? "true" : "false";
case VK_VARIANT_TYPE_UINT8_MWN:
case VK_VARIANT_TYPE_UINT16_MWN:
case VK_VARIANT_TYPE_UINT32_MWN:
case VK_VARIANT_TYPE_UINT64_MWN:
return std::to_string(variant.uintValue);
case VK_VARIANT_TYPE_INT8_MWN:
case VK_VARIANT_TYPE_INT16_MWN:
case VK_VARIANT_TYPE_INT32_MWN:
case VK_VARIANT_TYPE_INT64_MWN:
return std::to_string(variant.intValue);
case VK_VARIANT_TYPE_FLOAT_MWN:
case VK_VARIANT_TYPE_DOUBLE_MWN:
return std::to_string(variant.doubleValue);
case VK_VARIANT_TYPE_STRING_MWN:
return fmt::format("\"{}\"", variant.stringValue);
case VK_VARIANT_TYPE_VOID_POINTER_MWN:
return fmt::format("{}", fmt::ptr(variant.voidPointerValue)); // TODO: this doesnt make sense, store the original pointer!
case VK_VARIANT_TYPE_POINTER_MWN:
return fmt::format("{}", fmt::ptr(variant.pointerValue)); // TODO: this doesnt make sense, store the original pointer!
case VK_VARIANT_TYPE_ARRAY_MWN:
return fmt::format("<array of {}>", variant.arrayValue.numElements);
case VK_VARIANT_TYPE_IN_STRUCTURE_MWN:
return "<in struct>";
case VK_VARIANT_TYPE_OUT_STRUCTURE_MWN:
return "<out struct>";
case VK_VARIANT_TYPE_OBJECT_MWN:
return "<handle>";
default:
assert(0);
return "???";
}
}
#endif
#if 0
std::size_t calcVkStructHash(const void* structure, std::size_t appendTo)
{
if (structure == nullptr) {
return appendTo;
}
const vk::BaseInStructure* inStruct = static_cast<const vk::BaseInStructure*>(structure);
std::size_t hash = appendTo;
switch (inStruct->sType)
{
case vk::StructureType::eDescriptorSetLayoutBindingFlagsCreateInfo: {
const auto& flagsInfo = *static_cast<const vk::DescriptorSetLayoutBindingFlagsCreateInfo*>(structure);
for (std::uint32_t bindingIdx = 0; bindingIdx < flagsInfo.bindingCount; ++bindingIdx) {
hash = calcCrcSizeAppend(flagsInfo.pBindingFlags[bindingIdx], hash);
}
}
break;
default:
assert(false); // missing struct here, bad
break;
}
return calcVkStructHash(inStruct->pNext, hash);
}
#endif
vk::SampleCountFlagBits samplesToVk(unsigned samples) noexcept
{
switch (samples)
{
case 1:
return vk::SampleCountFlagBits::e1;
case 2:
return vk::SampleCountFlagBits::e2;
case 4:
return vk::SampleCountFlagBits::e4;
case 8:
return vk::SampleCountFlagBits::e8;
case 16:
return vk::SampleCountFlagBits::e16;
case 32:
return vk::SampleCountFlagBits::e32;
case 64:
return vk::SampleCountFlagBits::e64;
default:
logAndDie("Invalid sample count: {}.", samples);
}
}
vk::Format detectDepthBufferFormat(Device& device, unsigned samples) noexcept
{
const vk::SampleCountFlagBits sampleCount = samplesToVk(samples);
for (const vk::Format depthFormat : DEPTH_FORMATS)
{
try
{
const vk::ImageFormatProperties props = device.getVkPhysicalDevice().getImageFormatProperties(depthFormat, vk::ImageType::e2D, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eDepthStencilAttachment);
if (props.sampleCounts & sampleCount) {
return depthFormat;
}
}
catch(vk::FormatNotSupportedError&)
{
continue; // not supported
}
}
return vk::Format::eUndefined;
}
std::vector<unsigned> detectSupportedSampleCounts(Device& device) noexcept
{
std::vector<unsigned> result = {1};
for (const unsigned samples : {2, 4, 8, 16, 32, 64})
{
if (detectDepthBufferFormat(device, samples) != vk::Format::eUndefined) {
result.push_back(samples);
}
}
return result;
}
} // namespace iwa