/
ExpressionSlots.cpp
97 lines (79 loc) · 2.78 KB
/
ExpressionSlots.cpp
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
#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::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;
}
}