mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	glsl: Allow dynamic tracking of variable allocation
This commit is contained in:
		@@ -172,19 +172,28 @@ std::string GlslVersionSpecifier(const EmitContext& ctx) {
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsPreciseType(GlslVarType type) {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
    case GlslVarType::PrecF32:
 | 
			
		||||
    case GlslVarType::PrecF64:
 | 
			
		||||
        return true;
 | 
			
		||||
    default:
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DefineVariables(const EmitContext& ctx, std::string& header) {
 | 
			
		||||
    for (u32 i = 0; i < static_cast<u32>(GlslVarType::Void); ++i) {
 | 
			
		||||
        const auto type{static_cast<GlslVarType>(i)};
 | 
			
		||||
        const auto& tracker{ctx.var_alloc.GetUseTracker(type)};
 | 
			
		||||
        const auto type_name{ctx.var_alloc.GetGlslType(type)};
 | 
			
		||||
        const auto precise{
 | 
			
		||||
            (type == GlslVarType::PrecF32 || type == GlslVarType::PrecF64) ? "precise " : ""};
 | 
			
		||||
        const auto precise{IsPreciseType(type) ? "precise " : ""};
 | 
			
		||||
        // Temps/return types that are never used are stored at index 0
 | 
			
		||||
        if (tracker.uses_temp) {
 | 
			
		||||
            header += fmt::format("{}{} {}={}(0);", precise, type_name,
 | 
			
		||||
            header += fmt::format("{}{} t{}={}(0);", precise, type_name,
 | 
			
		||||
                                  ctx.var_alloc.Representation(0, type), type_name);
 | 
			
		||||
        }
 | 
			
		||||
        for (u32 index = 1; index <= tracker.num_used; ++index) {
 | 
			
		||||
        for (u32 index = 0; index < tracker.num_used; ++index) {
 | 
			
		||||
            header += fmt::format("{}{} {}={}(0);", precise, type_name,
 | 
			
		||||
                                  ctx.var_alloc.Representation(index, type), type_name);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -116,8 +116,8 @@ std::string VarAlloc::Define(IR::Inst& inst, GlslVarType type) {
 | 
			
		||||
        id.type.Assign(type);
 | 
			
		||||
        GetUseTracker(type).uses_temp = true;
 | 
			
		||||
        inst.SetDefinition<Id>(id);
 | 
			
		||||
        return "t" + Representation(inst.Definition<Id>());
 | 
			
		||||
    }
 | 
			
		||||
    return Representation(inst.Definition<Id>());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string VarAlloc::Define(IR::Inst& inst, IR::Type type) {
 | 
			
		||||
@@ -156,21 +156,27 @@ std::string VarAlloc::GetGlslType(IR::Type type) const {
 | 
			
		||||
 | 
			
		||||
Id VarAlloc::Alloc(GlslVarType type) {
 | 
			
		||||
    auto& use_tracker{GetUseTracker(type)};
 | 
			
		||||
    if (use_tracker.num_used < NUM_VARS) {
 | 
			
		||||
        for (size_t var = 1; var < NUM_VARS; ++var) {
 | 
			
		||||
            if (use_tracker.var_use[var]) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            use_tracker.num_used = std::max(use_tracker.num_used, var + 1);
 | 
			
		||||
            use_tracker.var_use[var] = true;
 | 
			
		||||
            Id ret{};
 | 
			
		||||
            ret.is_valid.Assign(1);
 | 
			
		||||
            ret.type.Assign(type);
 | 
			
		||||
            ret.index.Assign(static_cast<u32>(var));
 | 
			
		||||
            return ret;
 | 
			
		||||
    const auto num_vars{use_tracker.var_use.size()};
 | 
			
		||||
    for (size_t var = 0; var < num_vars; ++var) {
 | 
			
		||||
        if (use_tracker.var_use[var]) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        use_tracker.num_used = std::max(use_tracker.num_used, var + 1);
 | 
			
		||||
        use_tracker.var_use[var] = true;
 | 
			
		||||
        Id ret{};
 | 
			
		||||
        ret.is_valid.Assign(1);
 | 
			
		||||
        ret.type.Assign(type);
 | 
			
		||||
        ret.index.Assign(static_cast<u32>(var));
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
    throw NotImplementedException("Variable spilling");
 | 
			
		||||
    // Allocate a new variable
 | 
			
		||||
    use_tracker.var_use.push_back(true);
 | 
			
		||||
    Id ret{};
 | 
			
		||||
    ret.is_valid.Assign(1);
 | 
			
		||||
    ret.type.Assign(type);
 | 
			
		||||
    ret.index.Assign(static_cast<u32>(use_tracker.num_used));
 | 
			
		||||
    ++use_tracker.num_used;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VarAlloc::Free(Id id) {
 | 
			
		||||
 
 | 
			
		||||
@@ -57,11 +57,10 @@ static_assert(sizeof(Id) == sizeof(u32));
 | 
			
		||||
 | 
			
		||||
class VarAlloc {
 | 
			
		||||
public:
 | 
			
		||||
    static constexpr size_t NUM_VARS = 1023;
 | 
			
		||||
    struct UseTracker {
 | 
			
		||||
        size_t num_used{};
 | 
			
		||||
        std::bitset<NUM_VARS> var_use{};
 | 
			
		||||
        bool uses_temp{};
 | 
			
		||||
        size_t num_used{};
 | 
			
		||||
        std::vector<bool> var_use;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /// Used for explicit usages of variables, may revert to temporaries
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user