File: ExpressionSlots.cpp

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (115 lines) | stat: -rw-r--r-- 3,262 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "ExpressionSlots.h"

#include "ShaderExpression.h"

namespace shaders
{

ExpressionSlots::ExpressionSlots(Registers& registers) :
    _registers(registers)
{
    resize(IShaderLayer::Expression::NumExpressionSlots);
}

ExpressionSlots::ExpressionSlots(const ExpressionSlots& other, Registers& registers) :
    std::vector<ExpressionSlot>(other.size()),
    _registers(registers)
{
    for (auto i = 0; i < other.size(); ++i)
    {
        auto& thisSlot = at(i);
        auto& otherSlot = other.at(i);

        thisSlot.registerIndex = otherSlot.registerIndex;

        if (otherSlot.expression)
        {
            thisSlot.expression = otherSlot.expression->clone();
            thisSlot.expression->linkToSpecificRegister(_registers, thisSlot.registerIndex);
        }
    }
}

void ExpressionSlots::assign(IShaderLayer::Expression::Slot slot, const IShaderExpression::Ptr& newExpression, std::size_t defaultRegisterIndex)
{
    auto& expressionSlot = at(slot);

    if (!newExpression)
    {
        expressionSlot.expression.reset();
        expressionSlot.registerIndex = defaultRegisterIndex;
        return;
    }

    // Non-empty expression, overwrite if we have an existing expression in the slot
    // Beware of the fact that some expressions could be shared across slots, before re-using the same register
    if (expressionSlot.expression && !registerIsShared(expressionSlot.registerIndex))
    {
        // We assume that if there was an expression in the slot, it shouldn't point to the default registers
        assert(expressionSlot.registerIndex != defaultRegisterIndex);

        // Re-use the register index
        expressionSlot.expression = newExpression;
        expressionSlot.expression->linkToSpecificRegister(_registers, expressionSlot.registerIndex);
    }
    else
    {
        expressionSlot.expression = newExpression;
        expressionSlot.registerIndex = expressionSlot.expression->linkToRegister(_registers);
    }
}

void ExpressionSlots::assignFromString(IShaderLayer::Expression::Slot slot, const std::string& expressionString, std::size_t defaultRegisterIndex)
{
    // An empty string will clear the expression
    if (expressionString.empty())
    {
        assign(slot, IShaderExpression::Ptr(), defaultRegisterIndex);
        return;
    }

    // Attempt to parse the string
    auto expression = ShaderExpression::createFromString(expressionString);

    if (!expression)
    {
        return; // parsing failures will not overwrite the expression slot
    }

    assign(slot, expression, defaultRegisterIndex);
}

bool ExpressionSlots::expressionsAreEquivalent(IShaderLayer::Expression::Slot slotA, IShaderLayer::Expression::Slot slotB) const
{
    auto a = at(slotA);
    auto b = at(slotB);

    if (a.expression == b.expression)
    {
        return true;
    }

    if (a.expression && b.expression)
    {
        return a.expression->getExpressionString() == b.expression->getExpressionString();
    }

    return false;
}

bool ExpressionSlots::registerIsShared(std::size_t index) const
{
    std::size_t useCount = 0;

    for (const auto& slot : *this)
    {
        if (slot.registerIndex == index && ++useCount > 1)
        {
            return true;
        }
    }

    return false;
}

}