#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 ""; 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("", variant.arrayValue.numElements); case VK_VARIANT_TYPE_IN_STRUCTURE_MWN: return ""; case VK_VARIANT_TYPE_OUT_STRUCTURE_MWN: return ""; case VK_VARIANT_TYPE_OBJECT_MWN: return ""; 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(structure); std::size_t hash = appendTo; switch (inStruct->sType) { case vk::StructureType::eDescriptorSetLayoutBindingFlagsCreateInfo: { const auto& flagsInfo = *static_cast(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 detectSupportedSampleCounts(Device& device) noexcept { std::vector 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