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
|