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;
}
}
|