ShaderGenCommon: Add WriteSwitch
This commit is contained in:
parent
d8e347c8e8
commit
327126d1e8
|
@ -13,10 +13,11 @@
|
|||
|
||||
#include "Common/BitField.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/EnumMap.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/TypeUtils.h"
|
||||
|
||||
enum class APIType;
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
/**
|
||||
* Common interface for classes that need to go through the shader generation path
|
||||
|
@ -210,6 +211,64 @@ std::string BitfieldExtract(std::string_view source)
|
|||
static_cast<u32>(BitFieldT::NumBits()));
|
||||
}
|
||||
|
||||
template <auto last_member, typename = decltype(last_member)>
|
||||
void WriteSwitch(ShaderCode& out, APIType ApiType, std::string_view variable,
|
||||
const Common::EnumMap<std::string_view, last_member>& values, int indent,
|
||||
bool break_)
|
||||
{
|
||||
const bool make_switch = (ApiType == APIType::D3D);
|
||||
|
||||
// The second template argument is needed to avoid compile errors from ambiguity with multiple
|
||||
// enums with the same number of members in GCC prior to 8. See https://godbolt.org/z/xcKaW1seW
|
||||
// and https://godbolt.org/z/hz7Yqq1P5
|
||||
using enum_type = decltype(last_member);
|
||||
|
||||
// {:{}} is used to indent by formatting an empty string with a variable width
|
||||
if (make_switch)
|
||||
{
|
||||
out.Write("{:{}}switch ({}) {{\n", "", indent, variable);
|
||||
for (u32 i = 0; i <= static_cast<u32>(last_member); i++)
|
||||
{
|
||||
const enum_type key = static_cast<enum_type>(i);
|
||||
|
||||
// Assumes existence of an EnumFormatter
|
||||
out.Write("{:{}}case {:s}:\n", "", indent, key);
|
||||
// Note that this indentation behaves poorly for multi-line code
|
||||
if (!values[key].empty())
|
||||
out.Write("{:{}} {}\n", "", indent, values[key]);
|
||||
if (break_)
|
||||
out.Write("{:{}} break;\n", "", indent);
|
||||
}
|
||||
out.Write("{:{}}}}\n", "", indent);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate a tree of if statements recursively
|
||||
// std::function must be used because auto won't capture before initialization and thus can't be
|
||||
// used recursively
|
||||
std::function<void(u32, u32, u32)> BuildTree = [&](u32 cur_indent, u32 low, u32 high) {
|
||||
// Each generated statement is for low <= x < high
|
||||
if (high == low + 1)
|
||||
{
|
||||
// Down to 1 case (low <= x < low + 1 means x == low)
|
||||
const enum_type key = static_cast<enum_type>(low);
|
||||
// Note that this indentation behaves poorly for multi-line code
|
||||
out.Write("{:{}}{} // {}\n", "", cur_indent, values[key], key);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 mid = low + ((high - low) / 2);
|
||||
out.Write("{:{}}if ({} < {}u) {{\n", "", cur_indent, variable, mid);
|
||||
BuildTree(cur_indent + 2, low, mid);
|
||||
out.Write("{:{}}}} else {{\n", "", cur_indent);
|
||||
BuildTree(cur_indent + 2, mid, high);
|
||||
out.Write("{:{}}}}\n", "", cur_indent);
|
||||
}
|
||||
};
|
||||
BuildTree(indent, 0, static_cast<u32>(last_member) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Constant variable names
|
||||
#define I_COLORS "color"
|
||||
#define I_KCOLORS "k"
|
||||
|
|
Loading…
Reference in New Issue