Shader/Spirv: Put types and constants in the same section
This commit is contained in:
parent
cd23c01ace
commit
66a14721cb
|
|
@ -167,7 +167,7 @@ namespace Nz
|
||||||
UInt32 Register(Type t);
|
UInt32 Register(Type t);
|
||||||
UInt32 Register(Variable v);
|
UInt32 Register(Variable v);
|
||||||
|
|
||||||
void Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos, SpirvSection& types);
|
void Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos);
|
||||||
|
|
||||||
SpirvConstantCache& operator=(const SpirvConstantCache& cache) = delete;
|
SpirvConstantCache& operator=(const SpirvConstantCache& cache) = delete;
|
||||||
SpirvConstantCache& operator=(SpirvConstantCache&& cache) noexcept;
|
SpirvConstantCache& operator=(SpirvConstantCache&& cache) noexcept;
|
||||||
|
|
@ -183,7 +183,10 @@ namespace Nz
|
||||||
struct Eq;
|
struct Eq;
|
||||||
struct Internal;
|
struct Internal;
|
||||||
|
|
||||||
void WriteStruct(const Structure& structData, UInt32 resultId, SpirvSection& annotations, SpirvSection& debugInfos, SpirvSection& types);
|
void Write(const AnyConstant& constant, UInt32 resultId, SpirvSection& constants);
|
||||||
|
void Write(const AnyType& type, UInt32 resultId, SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos);
|
||||||
|
|
||||||
|
void WriteStruct(const Structure& structData, UInt32 resultId, SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos);
|
||||||
|
|
||||||
std::unique_ptr<Internal> m_internal;
|
std::unique_ptr<Internal> m_internal;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,12 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||||
|
|
||||||
|
template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;
|
||||||
|
}
|
||||||
struct SpirvConstantCache::Eq
|
struct SpirvConstantCache::Eq
|
||||||
{
|
{
|
||||||
bool Compare(const ConstantBool& lhs, const ConstantBool& rhs) const
|
bool Compare(const ConstantBool& lhs, const ConstantBool& rhs) const
|
||||||
|
|
@ -381,8 +387,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
tsl::ordered_map<AnyConstant, UInt32 /*id*/, AnyHasher, Eq> constantIds;
|
tsl::ordered_map<std::variant<AnyConstant, AnyType>, UInt32 /*id*/, AnyHasher, Eq> ids;
|
||||||
tsl::ordered_map<AnyType, UInt32 /*id*/, AnyHasher, Eq> typeIds;
|
|
||||||
tsl::ordered_map<Variable, UInt32 /*id*/, AnyHasher, Eq> variableIds;
|
tsl::ordered_map<Variable, UInt32 /*id*/, AnyHasher, Eq> variableIds;
|
||||||
tsl::ordered_map<Structure, FieldOffsets /*fieldOffsets*/, AnyHasher, Eq> structureSizes;
|
tsl::ordered_map<Structure, FieldOffsets /*fieldOffsets*/, AnyHasher, Eq> structureSizes;
|
||||||
UInt32& nextResultId;
|
UInt32& nextResultId;
|
||||||
|
|
@ -399,8 +404,8 @@ namespace Nz
|
||||||
|
|
||||||
UInt32 SpirvConstantCache::GetId(const Constant& c)
|
UInt32 SpirvConstantCache::GetId(const Constant& c)
|
||||||
{
|
{
|
||||||
auto it = m_internal->constantIds.find(c.constant);
|
auto it = m_internal->ids.find(c.constant);
|
||||||
if (it == m_internal->constantIds.end())
|
if (it == m_internal->ids.end())
|
||||||
throw std::runtime_error("constant is not registered");
|
throw std::runtime_error("constant is not registered");
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
@ -408,8 +413,8 @@ namespace Nz
|
||||||
|
|
||||||
UInt32 SpirvConstantCache::GetId(const Type& t)
|
UInt32 SpirvConstantCache::GetId(const Type& t)
|
||||||
{
|
{
|
||||||
auto it = m_internal->typeIds.find(t.type);
|
auto it = m_internal->ids.find(t.type);
|
||||||
if (it == m_internal->typeIds.end())
|
if (it == m_internal->ids.end())
|
||||||
throw std::runtime_error("constant is not registered");
|
throw std::runtime_error("constant is not registered");
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
@ -431,12 +436,12 @@ namespace Nz
|
||||||
DepRegisterer registerer(*this);
|
DepRegisterer registerer(*this);
|
||||||
registerer.Register(constant);
|
registerer.Register(constant);
|
||||||
|
|
||||||
std::size_t h = m_internal->typeIds.hash_function()(constant);
|
std::size_t h = m_internal->ids.hash_function()(constant);
|
||||||
auto it = m_internal->constantIds.find(constant, h);
|
auto it = m_internal->ids.find(constant, h);
|
||||||
if (it == m_internal->constantIds.end())
|
if (it == m_internal->ids.end())
|
||||||
{
|
{
|
||||||
UInt32 resultId = m_internal->nextResultId++;
|
UInt32 resultId = m_internal->nextResultId++;
|
||||||
it = m_internal->constantIds.emplace(std::move(constant), resultId).first;
|
it = m_internal->ids.emplace(std::move(constant), resultId).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
return it.value();
|
return it.value();
|
||||||
|
|
@ -449,12 +454,12 @@ namespace Nz
|
||||||
DepRegisterer registerer(*this);
|
DepRegisterer registerer(*this);
|
||||||
registerer.Register(type);
|
registerer.Register(type);
|
||||||
|
|
||||||
std::size_t h = m_internal->typeIds.hash_function()(type);
|
std::size_t h = m_internal->ids.hash_function()(type);
|
||||||
auto it = m_internal->typeIds.find(type, h);
|
auto it = m_internal->ids.find(type, h);
|
||||||
if (it == m_internal->typeIds.end())
|
if (it == m_internal->ids.end())
|
||||||
{
|
{
|
||||||
UInt32 resultId = m_internal->nextResultId++;
|
UInt32 resultId = m_internal->nextResultId++;
|
||||||
it = m_internal->typeIds.emplace(std::move(type), resultId).first;
|
it = m_internal->ids.emplace(std::move(type), resultId).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
return it.value();
|
return it.value();
|
||||||
|
|
@ -476,131 +481,19 @@ namespace Nz
|
||||||
return it.value();
|
return it.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvConstantCache::Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos, SpirvSection& types)
|
void SpirvConstantCache::Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos)
|
||||||
{
|
{
|
||||||
for (auto&& [type, id] : m_internal->typeIds)
|
for (auto&& [type, id] : m_internal->ids)
|
||||||
{
|
{
|
||||||
UInt32 resultId = id;
|
UInt32 resultId = id;
|
||||||
|
|
||||||
std::visit([&](auto&& arg)
|
std::visit(overloaded
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
[&](const AnyConstant& constant) { Write(constant, resultId, constants); },
|
||||||
|
[&](const AnyType& type) { Write(type, resultId, annotations, constants, debugInfos); },
|
||||||
if constexpr (std::is_same_v<T, Bool>)
|
|
||||||
types.Append(SpirvOp::OpTypeBool, resultId);
|
|
||||||
else if constexpr (std::is_same_v<T, Float>)
|
|
||||||
types.Append(SpirvOp::OpTypeFloat, resultId, arg.width);
|
|
||||||
else if constexpr (std::is_same_v<T, Function>)
|
|
||||||
{
|
|
||||||
types.AppendVariadic(SpirvOp::OpTypeFunction, [&](const auto& appender)
|
|
||||||
{
|
|
||||||
appender(resultId);
|
|
||||||
appender(GetId(*arg.returnType));
|
|
||||||
|
|
||||||
for (const auto& param : arg.parameters)
|
|
||||||
appender(GetId(*param));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, Image>)
|
|
||||||
{
|
|
||||||
UInt32 depth;
|
|
||||||
if (arg.depth.has_value())
|
|
||||||
depth = (*arg.depth) ? 1 : 0;
|
|
||||||
else
|
|
||||||
depth = 2;
|
|
||||||
|
|
||||||
UInt32 sampled;
|
|
||||||
if (arg.sampled.has_value())
|
|
||||||
sampled = (*arg.sampled) ? 1 : 0;
|
|
||||||
else
|
|
||||||
sampled = 2;
|
|
||||||
|
|
||||||
types.AppendVariadic(SpirvOp::OpTypeImage, [&](const auto& appender)
|
|
||||||
{
|
|
||||||
appender(resultId);
|
|
||||||
appender(GetId(*arg.sampledType));
|
|
||||||
appender(arg.dim);
|
|
||||||
appender(depth);
|
|
||||||
appender(arg.arrayed);
|
|
||||||
appender(arg.multisampled);
|
|
||||||
appender(sampled);
|
|
||||||
appender(arg.format);
|
|
||||||
|
|
||||||
if (arg.qualifier)
|
|
||||||
appender(*arg.qualifier);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, Integer>)
|
|
||||||
types.Append(SpirvOp::OpTypeInt, resultId, arg.width, arg.signedness);
|
|
||||||
else if constexpr (std::is_same_v<T, Matrix>)
|
|
||||||
types.Append(SpirvOp::OpTypeMatrix, resultId, GetId(*arg.columnType), arg.columnCount);
|
|
||||||
else if constexpr (std::is_same_v<T, Pointer>)
|
|
||||||
types.Append(SpirvOp::OpTypePointer, resultId, arg.storageClass, GetId(*arg.type));
|
|
||||||
else if constexpr (std::is_same_v<T, SampledImage>)
|
|
||||||
types.Append(SpirvOp::OpTypeSampledImage, resultId, GetId(*arg.image));
|
|
||||||
else if constexpr (std::is_same_v<T, Structure>)
|
|
||||||
WriteStruct(arg, resultId, annotations, debugInfos, types);
|
|
||||||
else if constexpr (std::is_same_v<T, Vector>)
|
|
||||||
types.Append(SpirvOp::OpTypeVector, resultId, GetId(*arg.componentType), arg.componentCount);
|
|
||||||
else if constexpr (std::is_same_v<T, Void>)
|
|
||||||
types.Append(SpirvOp::OpTypeVoid, resultId);
|
|
||||||
else
|
|
||||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
|
||||||
}, type);
|
}, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto&& [constant, id] : m_internal->constantIds)
|
|
||||||
{
|
|
||||||
UInt32 resultId = id;
|
|
||||||
|
|
||||||
std::visit([&](auto&& arg)
|
|
||||||
{
|
|
||||||
using T = std::decay_t<decltype(arg)>;
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, ConstantBool>)
|
|
||||||
constants.Append((arg.value) ? SpirvOp::OpConstantTrue : SpirvOp::OpConstantFalse, resultId);
|
|
||||||
else if constexpr (std::is_same_v<T, ConstantComposite>)
|
|
||||||
{
|
|
||||||
constants.AppendVariadic(SpirvOp::OpConstantComposite, [&](const auto& appender)
|
|
||||||
{
|
|
||||||
appender(GetId(arg.type->type));
|
|
||||||
appender(resultId);
|
|
||||||
|
|
||||||
for (const auto& value : arg.values)
|
|
||||||
appender(GetId(value->constant));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, ConstantScalar>)
|
|
||||||
{
|
|
||||||
std::visit([&](auto&& arg)
|
|
||||||
{
|
|
||||||
using T = std::decay_t<decltype(arg)>;
|
|
||||||
|
|
||||||
UInt32 typeId;
|
|
||||||
if constexpr (std::is_same_v<T, double>)
|
|
||||||
typeId = GetId({ Float{ 64 } });
|
|
||||||
else if constexpr (std::is_same_v<T, float>)
|
|
||||||
typeId = GetId({ Float{ 32 } });
|
|
||||||
else if constexpr (std::is_same_v<T, Int32>)
|
|
||||||
typeId = GetId({ Integer{ 32, 1 } });
|
|
||||||
else if constexpr (std::is_same_v<T, Int64>)
|
|
||||||
typeId = GetId({ Integer{ 64, 1 } });
|
|
||||||
else if constexpr (std::is_same_v<T, UInt32>)
|
|
||||||
typeId = GetId({ Integer{ 32, 0 } });
|
|
||||||
else if constexpr (std::is_same_v<T, UInt64>)
|
|
||||||
typeId = GetId({ Integer{ 64, 0 } });
|
|
||||||
else
|
|
||||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
|
||||||
|
|
||||||
constants.Append(SpirvOp::OpConstant, typeId, resultId, SpirvSection::Raw{ &arg, sizeof(arg) });
|
|
||||||
|
|
||||||
}, arg.value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
|
||||||
}, constant);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto&& [variable, id] : m_internal->variableIds)
|
for (auto&& [variable, id] : m_internal->variableIds)
|
||||||
{
|
{
|
||||||
UInt32 resultId = id;
|
UInt32 resultId = id;
|
||||||
|
|
@ -781,9 +674,128 @@ namespace Nz
|
||||||
}, type);
|
}, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvConstantCache::WriteStruct(const Structure& structData, UInt32 resultId, SpirvSection& annotations, SpirvSection& debugInfos, SpirvSection& types)
|
void SpirvConstantCache::Write(const AnyConstant& constant, UInt32 resultId, SpirvSection& constants)
|
||||||
{
|
{
|
||||||
types.AppendVariadic(SpirvOp::OpTypeStruct, [&](const auto& appender)
|
std::visit([&](auto&& arg)
|
||||||
|
{
|
||||||
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, ConstantBool>)
|
||||||
|
constants.Append((arg.value) ? SpirvOp::OpConstantTrue : SpirvOp::OpConstantFalse, resultId);
|
||||||
|
else if constexpr (std::is_same_v<T, ConstantComposite>)
|
||||||
|
{
|
||||||
|
constants.AppendVariadic(SpirvOp::OpConstantComposite, [&](const auto& appender)
|
||||||
|
{
|
||||||
|
appender(GetId(arg.type->type));
|
||||||
|
appender(resultId);
|
||||||
|
|
||||||
|
for (const auto& value : arg.values)
|
||||||
|
appender(GetId(value->constant));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, ConstantScalar>)
|
||||||
|
{
|
||||||
|
std::visit([&](auto&& arg)
|
||||||
|
{
|
||||||
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
|
UInt32 typeId;
|
||||||
|
if constexpr (std::is_same_v<T, double>)
|
||||||
|
typeId = GetId({ Float{ 64 } });
|
||||||
|
else if constexpr (std::is_same_v<T, float>)
|
||||||
|
typeId = GetId({ Float{ 32 } });
|
||||||
|
else if constexpr (std::is_same_v<T, Int32>)
|
||||||
|
typeId = GetId({ Integer{ 32, 1 } });
|
||||||
|
else if constexpr (std::is_same_v<T, Int64>)
|
||||||
|
typeId = GetId({ Integer{ 64, 1 } });
|
||||||
|
else if constexpr (std::is_same_v<T, UInt32>)
|
||||||
|
typeId = GetId({ Integer{ 32, 0 } });
|
||||||
|
else if constexpr (std::is_same_v<T, UInt64>)
|
||||||
|
typeId = GetId({ Integer{ 64, 0 } });
|
||||||
|
else
|
||||||
|
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||||
|
|
||||||
|
constants.Append(SpirvOp::OpConstant, typeId, resultId, SpirvSection::Raw{ &arg, sizeof(arg) });
|
||||||
|
|
||||||
|
}, arg.value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||||
|
}, constant);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvConstantCache::Write(const AnyType& type, UInt32 resultId, SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos)
|
||||||
|
{
|
||||||
|
std::visit([&](auto&& arg)
|
||||||
|
{
|
||||||
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, Bool>)
|
||||||
|
constants.Append(SpirvOp::OpTypeBool, resultId);
|
||||||
|
else if constexpr (std::is_same_v<T, Float>)
|
||||||
|
constants.Append(SpirvOp::OpTypeFloat, resultId, arg.width);
|
||||||
|
else if constexpr (std::is_same_v<T, Function>)
|
||||||
|
{
|
||||||
|
constants.AppendVariadic(SpirvOp::OpTypeFunction, [&](const auto& appender)
|
||||||
|
{
|
||||||
|
appender(resultId);
|
||||||
|
appender(GetId(*arg.returnType));
|
||||||
|
|
||||||
|
for (const auto& param : arg.parameters)
|
||||||
|
appender(GetId(*param));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, Image>)
|
||||||
|
{
|
||||||
|
UInt32 depth;
|
||||||
|
if (arg.depth.has_value())
|
||||||
|
depth = (*arg.depth) ? 1 : 0;
|
||||||
|
else
|
||||||
|
depth = 2;
|
||||||
|
|
||||||
|
UInt32 sampled;
|
||||||
|
if (arg.sampled.has_value())
|
||||||
|
sampled = (*arg.sampled) ? 1 : 0;
|
||||||
|
else
|
||||||
|
sampled = 2;
|
||||||
|
|
||||||
|
constants.AppendVariadic(SpirvOp::OpTypeImage, [&](const auto& appender)
|
||||||
|
{
|
||||||
|
appender(resultId);
|
||||||
|
appender(GetId(*arg.sampledType));
|
||||||
|
appender(arg.dim);
|
||||||
|
appender(depth);
|
||||||
|
appender(arg.arrayed);
|
||||||
|
appender(arg.multisampled);
|
||||||
|
appender(sampled);
|
||||||
|
appender(arg.format);
|
||||||
|
|
||||||
|
if (arg.qualifier)
|
||||||
|
appender(*arg.qualifier);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, Integer>)
|
||||||
|
constants.Append(SpirvOp::OpTypeInt, resultId, arg.width, arg.signedness);
|
||||||
|
else if constexpr (std::is_same_v<T, Matrix>)
|
||||||
|
constants.Append(SpirvOp::OpTypeMatrix, resultId, GetId(*arg.columnType), arg.columnCount);
|
||||||
|
else if constexpr (std::is_same_v<T, Pointer>)
|
||||||
|
constants.Append(SpirvOp::OpTypePointer, resultId, arg.storageClass, GetId(*arg.type));
|
||||||
|
else if constexpr (std::is_same_v<T, SampledImage>)
|
||||||
|
constants.Append(SpirvOp::OpTypeSampledImage, resultId, GetId(*arg.image));
|
||||||
|
else if constexpr (std::is_same_v<T, Structure>)
|
||||||
|
WriteStruct(arg, resultId, annotations, constants, debugInfos);
|
||||||
|
else if constexpr (std::is_same_v<T, Vector>)
|
||||||
|
constants.Append(SpirvOp::OpTypeVector, resultId, GetId(*arg.componentType), arg.componentCount);
|
||||||
|
else if constexpr (std::is_same_v<T, Void>)
|
||||||
|
constants.Append(SpirvOp::OpTypeVoid, resultId);
|
||||||
|
else
|
||||||
|
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||||
|
}, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvConstantCache::WriteStruct(const Structure& structData, UInt32 resultId, SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos)
|
||||||
|
{
|
||||||
|
constants.AppendVariadic(SpirvOp::OpTypeStruct, [&](const auto& appender)
|
||||||
{
|
{
|
||||||
appender(resultId);
|
appender(resultId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,6 @@ namespace Nz
|
||||||
SpirvSection constants;
|
SpirvSection constants;
|
||||||
SpirvSection debugInfo;
|
SpirvSection debugInfo;
|
||||||
SpirvSection annotations;
|
SpirvSection annotations;
|
||||||
SpirvSection types;
|
|
||||||
SpirvSection instructions;
|
SpirvSection instructions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -398,7 +397,7 @@ namespace Nz
|
||||||
|
|
||||||
assert(entryPointIndex != std::numeric_limits<std::size_t>::max());
|
assert(entryPointIndex != std::numeric_limits<std::size_t>::max());
|
||||||
|
|
||||||
m_currentState->constantTypeCache.Write(m_currentState->annotations, m_currentState->constants, m_currentState->debugInfo, m_currentState->types);
|
m_currentState->constantTypeCache.Write(m_currentState->annotations, m_currentState->constants, m_currentState->debugInfo);
|
||||||
|
|
||||||
AppendHeader();
|
AppendHeader();
|
||||||
|
|
||||||
|
|
@ -446,7 +445,6 @@ namespace Nz
|
||||||
MergeBlocks(ret, state.header);
|
MergeBlocks(ret, state.header);
|
||||||
MergeBlocks(ret, state.debugInfo);
|
MergeBlocks(ret, state.debugInfo);
|
||||||
MergeBlocks(ret, state.annotations);
|
MergeBlocks(ret, state.annotations);
|
||||||
MergeBlocks(ret, state.types);
|
|
||||||
MergeBlocks(ret, state.constants);
|
MergeBlocks(ret, state.constants);
|
||||||
MergeBlocks(ret, state.instructions);
|
MergeBlocks(ret, state.instructions);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue