276 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			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
 |