summaryrefslogtreecommitdiff
path: root/source/slang/slang-capability.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-capability.cpp')
-rw-r--r--source/slang/slang-capability.cpp144
1 files changed, 113 insertions, 31 deletions
diff --git a/source/slang/slang-capability.cpp b/source/slang/slang-capability.cpp
index 21b2641b4..2c3069f61 100644
--- a/source/slang/slang-capability.cpp
+++ b/source/slang/slang-capability.cpp
@@ -100,16 +100,16 @@ bool isDirectChildOfAbstractAtom(CapabilityAtom name)
return _getInfo(name).abstractBase != CapabilityName::Invalid;
}
-bool isTargetVersionAtom(CapabilityName name)
+bool isTargetVersionAtom(CapabilityAtom name)
{
- if (name >= CapabilityName::spirv_1_0 && name <= getLatestSpirvAtom())
+ if (name >= CapabilityAtom::_spirv_1_0 && name <= getLatestSpirvAtom())
return true;
- if (name >= CapabilityName::metallib_2_3 && name <= getLatestMetalAtom())
+ if (name >= CapabilityAtom::metallib_2_3 && name <= getLatestMetalAtom())
return true;
return false;
}
-bool isSpirvExtensionAtom(CapabilityName name)
+bool isSpirvExtensionAtom(CapabilityAtom name)
{
return UnownedStringSlice(_getInfo(name).name).startsWith("SPV_");
}
@@ -124,26 +124,26 @@ CapabilityName findCapabilityName(UnownedStringSlice const& name)
return result;
}
-CapabilityName getLatestSpirvAtom()
+inline CapabilityAtom getLatestSpirvAtom()
{
- static CapabilityName result = CapabilityName::Invalid;
- if (result == CapabilityName::Invalid)
+ static CapabilityAtom result = CapabilityAtom::Invalid;
+ if (result == CapabilityAtom::Invalid)
{
- CapabilitySet latestSpirvCapSet = CapabilitySet(CapabilityName::spirv_latest);
+ CapabilitySet latestSpirvCapSet = CapabilitySet(CapabilityName::_spirv_latest);
auto latestSpirvCapSetElements = latestSpirvCapSet.getAtomSets()->getElements<CapabilityAtom>();
- result = (CapabilityName)latestSpirvCapSetElements[latestSpirvCapSetElements.getCount() - 2]; //-1 gets shader stage
+ result = asAtom(latestSpirvCapSetElements[latestSpirvCapSetElements.getCount() - 2]); //-1 gets shader stage
}
return result;
}
-CapabilityName getLatestMetalAtom()
+CapabilityAtom getLatestMetalAtom()
{
- static CapabilityName result = CapabilityName::Invalid;
- if (result == CapabilityName::Invalid)
+ static CapabilityAtom result = CapabilityAtom::Invalid;
+ if (result == CapabilityAtom::Invalid)
{
CapabilitySet latestMetalCapSet = CapabilitySet(CapabilityName::metallib_latest);
auto latestMetalCapSetElements = latestMetalCapSet.getAtomSets()->getElements<CapabilityAtom>();
- result = (CapabilityName)latestMetalCapSetElements[latestMetalCapSetElements.getCount() - 2]; //-1 gets shader stage
+ result = asAtom(latestMetalCapSetElements[latestMetalCapSetElements.getCount() - 2]); //-1 gets shader stage
}
return result;
}
@@ -175,7 +175,7 @@ CapabilityAtom getTargetAtomInSet(const CapabilityAtomSet& atomSet)
auto iter = out.begin();
if (iter == out.end())
return CapabilityAtom::Invalid;
- return (CapabilityAtom)*iter;
+ return asAtom(*iter);
}
CapabilityAtom getStageAtomInSet(const CapabilityAtomSet& atomSet)
@@ -186,7 +186,7 @@ CapabilityAtom getStageAtomInSet(const CapabilityAtomSet& atomSet)
auto iter = out.begin();
if (iter == out.end())
return CapabilityAtom::Invalid;
- return (CapabilityAtom)*iter;
+ return asAtom(*iter);
}
template<CapabilityName keyholeAtomToPermuteWith>
@@ -201,11 +201,11 @@ void CapabilitySet::addPermutationsOfConjunctionForEachInContainer(CapabilityAto
if constexpr (keyholeAtomToPermuteWith == CapabilityName::target)
{
- addConjunction(conjunctionPermutation, (CapabilityAtom)atom, knownStageAtom);
+ addConjunction(conjunctionPermutation, asAtom(atom), knownStageAtom);
}
else if constexpr (keyholeAtomToPermuteWith == CapabilityName::stage)
{
- addConjunction(conjunctionPermutation, knownTargetAtom, (CapabilityAtom)atom);
+ addConjunction(conjunctionPermutation, knownTargetAtom, asAtom(atom));
}
else
{
@@ -394,17 +394,25 @@ bool CapabilitySet::implies(CapabilityAtom atom) const
return this->implies(tmpSet);
}
-bool CapabilitySet::implies(CapabilitySet const& other, const bool onlyRequireSingleImply) const
+CapabilitySet::ImpliesReturnFlags CapabilitySet::_implies(CapabilitySet const& otherSet, ImpliesFlags flags) const
{
// x implies (c | d) only if (x implies c) and (x implies d).
- for (const auto& otherTarget : other.m_targetSets)
+ bool onlyRequireSingleImply = ((int)flags & (int)ImpliesFlags::OnlyRequireASingleValidImply);
+ int flagsCollected = (int)CapabilitySet::ImpliesReturnFlags::NotImplied;
+
+ if (otherSet.isEmpty())
+ return CapabilitySet::ImpliesReturnFlags::Implied;
+
+ for (const auto& otherTarget : otherSet.m_targetSets)
{
auto thisTarget = this->m_targetSets.tryGetValue(otherTarget.first);
if (!thisTarget)
{
+ if (onlyRequireSingleImply)
+ continue;
// 'this' lacks a target 'other' has.
- return false;
+ return CapabilitySet::ImpliesReturnFlags::NotImplied;
}
for (const auto& otherStage : otherTarget.second.shaderStageSets)
@@ -412,31 +420,44 @@ bool CapabilitySet::implies(CapabilitySet const& other, const bool onlyRequireSi
auto thisStage = thisTarget->shaderStageSets.tryGetValue(otherStage.first);
if (!thisStage)
{
+ if (onlyRequireSingleImply)
+ continue;
// 'this' lacks a stage 'other' has.
- return false;
+ return CapabilitySet::ImpliesReturnFlags::NotImplied;
}
// all stage sets that are in 'other' must be contained by 'this'
- if(thisStage->atomSet)
+ if (thisStage->atomSet)
{
auto& thisStageSet = thisStage->atomSet.value();
- if(otherStage.second.atomSet)
- {
- if (!onlyRequireSingleImply)
+ if (otherStage.second.atomSet)
+ {
+ auto contained = thisStageSet.contains(otherStage.second.atomSet.value());
+ if (!onlyRequireSingleImply && !contained)
{
- if (!thisStageSet.contains(otherStage.second.atomSet.value()))
- return false;
+ return CapabilitySet::ImpliesReturnFlags::NotImplied;
}
- else
+ else if (onlyRequireSingleImply && contained)
{
- if (thisStageSet.contains(otherStage.second.atomSet.value()))
- return true;
+ return CapabilitySet::ImpliesReturnFlags::Implied;
}
}
}
}
}
- return !onlyRequireSingleImply;
+ if (!onlyRequireSingleImply)
+ flagsCollected |= (int)CapabilitySet::ImpliesReturnFlags::Implied;
+
+ return (CapabilitySet::ImpliesReturnFlags)flagsCollected;
+}
+
+bool CapabilitySet::implies(CapabilitySet const& other) const
+{
+ return (int)_implies(other, ImpliesFlags::None) & (int)CapabilitySet::ImpliesReturnFlags::Implied;
+}
+CapabilitySet::ImpliesReturnFlags CapabilitySet::atLeastOneSetImpliedInOther(CapabilitySet const& other) const
+{
+ return _implies(other, ImpliesFlags::OnlyRequireASingleValidImply);
}
void CapabilityTargetSet::unionWith(const CapabilityTargetSet& other)
@@ -827,6 +848,53 @@ bool CapabilitySet::checkCapabilityRequirement(CapabilitySet const& available, C
return true;
}
+/// Converts spirv version atom to the glsl_spirv equivlent. If not possible, Invalid is returned
+inline CapabilityName maybeConvertSpirvVersionToGlslSpirvVersion(CapabilityName& atom)
+{
+ if (atom >= CapabilityName::_spirv_1_0 && asAtom(atom) <= getLatestSpirvAtom())
+ {
+ return (CapabilityName)((Int)CapabilityName::glsl_spirv_1_0 + ((Int)atom - (Int)CapabilityName::_spirv_1_0));
+ }
+ return CapabilityName::Invalid;
+}
+
+void CapabilitySet::addSpirvVersionFromOtherAsGlslSpirvVersion(CapabilitySet& other)
+{
+ if (auto* otherTargetSet = other.m_targetSets.tryGetValue(CapabilityAtom::spirv))
+ {
+ auto* thisTargetSet = m_targetSets.tryGetValue(CapabilityAtom::glsl);
+ if (!thisTargetSet)
+ return;
+
+ for (auto& otherStageSet : otherTargetSet->shaderStageSets)
+ {
+ if (!otherStageSet.second.atomSet)
+ continue;
+
+ auto* thisStageSet = thisTargetSet->shaderStageSets.tryGetValue(otherStageSet.first);
+ if (!thisStageSet || !thisStageSet->atomSet)
+ continue;
+
+ CapabilityAtomSet::Iterator otherAtom = otherStageSet.second.atomSet->begin();
+ while (otherAtom != otherStageSet.second.atomSet->end())
+ {
+ otherAtom++;
+ auto otherAtomName = (CapabilityName)*otherAtom;
+ if (otherAtomName > (CapabilityName)getLatestSpirvAtom())
+ {
+ otherAtom = otherStageSet.second.atomSet->end();
+ continue;
+ }
+ auto maybeConvertedSpirvVersionAtom = maybeConvertSpirvVersionToGlslSpirvVersion(otherAtomName);
+ if (maybeConvertedSpirvVersionAtom == CapabilityName::Invalid)
+ continue;
+
+ thisStageSet->atomSet->add((UInt)maybeConvertedSpirvVersionAtom);
+ }
+ }
+ }
+}
+
void printDiagnosticArg(StringBuilder& sb, const CapabilitySet& capSet)
{
bool isFirstSet = true;
@@ -864,6 +932,20 @@ void printDiagnosticArg(StringBuilder& sb, CapabilityName name)
sb << _getInfo(name).name;
}
+void printDiagnosticArg(StringBuilder& sb, List<CapabilityAtom>& list)
+{
+ sb << "{";
+ auto count = list.getCount();
+ for(Index i = 0; i < count; i++)
+ {
+ printDiagnosticArg(sb, list[i]);
+ if (i + 1 != count)
+ sb << ", ";
+ }
+ sb << "}";
+}
+
+
#ifdef UNIT_TEST_CAPABILITIES
#define CHECK_CAPS(inData) SLANG_ASSERT(inData>0)