#pragma once
/*
VulkanFramework
by John Ryland
Copyright (c) 2023
*/
////////////////////////////////////////////////////////////////////////////////////
// Vulkan Attribute Binding
#include "VulkanDevice.h"
namespace Vulkan {
// decorate the value type with a format description
template <typename T, enum VkFormat fmt>
struct Attribute
{
T value;
static const VkFormat format = fmt;
};
// extract the format and member offsets of the struct in to VkVertexInputAttributeDescriptions
template <typename ObjT>
struct AttributeVisitor
{
template <typename T>
void Visit(T& member)
{
VkVertexInputAttributeDescription attribDesc {};
attribDesc.binding = 0;
attribDesc.location = ret.size();
attribDesc.format = T::format;
attribDesc.offset = size_t(&member) - size_t(&obj);
ret.push_back(attribDesc);
}
ObjT obj;
std::vector<VkVertexInputAttributeDescription> ret;
};
template <typename ObjT>
std::vector<VkVertexInputAttributeDescription> GetAttributes()
{
AttributeVisitor<ObjT> visitor;
visitor.obj.Visit(visitor);
return visitor.ret;
}
template <typename ObjT>
std::vector<VkVertexInputBindingDescription> GetBindings()
{
std::vector<VkVertexInputBindingDescription> ret;
VkVertexInputBindingDescription bindingDescription {};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(ObjT);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
ret.push_back(bindingDescription);
return ret;
}
template <typename ObjT>
struct EqualityVisitor
{
template <typename T>
void Visit(T& member)
{
T* otherMember = (T*)(size_t(&other) + size_t(&member) - size_t(&self));
ret = ret && (member.value == otherMember->value);
}
const ObjT& self;
const ObjT& other;
bool ret = true;
};
template <typename ObjT>
struct IsEqual
{
bool operator()(const ObjT& self, const ObjT& other) const
{
EqualityVisitor<ObjT> visitor{ self, other };
self.Visit(visitor);
return visitor.ret;
}
};
template <typename ObjT>
struct HashVisitor
{
template <typename T>
void Visit(T& member)
{
ret = ret ^ std::hash<decltype(T::value)>()(member.value);
}
size_t ret = 0;
};
template <typename ObjT>
struct Hash
{
size_t operator()(const ObjT& obj) const
{
HashVisitor<ObjT> visitor;
obj.Visit(visitor);
return visitor.ret;
}
};
} // Vulkan namespace