Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify CapabilitySet Diagnostic Printing #4678

Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 158 additions & 25 deletions source/slang/slang-capability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,57 @@ bool isCapabilityDerivedFrom(CapabilityAtom atom, CapabilityAtom base)
return false;
}

//CapabilityAtomSet

CapabilityAtomSet CapabilityAtomSet::removeImpliedAtoms() const
{
// plan is to add all atoms which is impled (=>) another atom.
// Implying an atom appears in the form of atom1=>atom2 or atom2=>atom1.
Dictionary<CapabilityAtom, bool> candidateForSimplifiedList;
CapabilityAtomSet simplifiedSet;
for (auto atom1UInt : *this)
{
CapabilityAtom atom1 = (CapabilityAtom)atom1UInt;
if (!candidateForSimplifiedList.addIfNotExists(atom1, true)
&& candidateForSimplifiedList[atom1] == false)
continue;

for (auto atom2UInt : *this)
{
if (atom1UInt == atom2UInt)
continue;

CapabilityAtom atom2 = (CapabilityAtom)atom2UInt;
if (!candidateForSimplifiedList.addIfNotExists(atom2, true)
&& candidateForSimplifiedList[atom2] == false)
continue;

auto atomInfo1 = _getInfo(atom1).canonicalRepresentation;
auto atomInfo2 = _getInfo(atom2).canonicalRepresentation;
for (auto atomSet1 : atomInfo1)
{
for (auto atomSet2 : atomInfo2)
{
if (atomSet1->contains(*atomSet2))
{
candidateForSimplifiedList[atom2] = false;
continue;
}
else if (atomSet2->contains(*atomSet1))
{
candidateForSimplifiedList[atom1] = false;
continue;
}
}
}
}
}
for (auto i : candidateForSimplifiedList)
if(i.second)
simplifiedSet.add((UInt)i.first);
return simplifiedSet;
}

//// CapabiltySet

CapabilityAtom getTargetAtomInSet(const CapabilityAtomSet& atomSet)
Expand Down Expand Up @@ -897,31 +948,118 @@ void CapabilitySet::addSpirvVersionFromOtherAsGlslSpirvVersion(CapabilitySet& ot
}
}

void printDiagnosticArg(StringBuilder& sb, const CapabilitySet& capSet)
UnownedStringSlice capabilityNameToStringWithoutPrefix(CapabilityName capabilityName)
{
auto name = capabilityNameToString(capabilityName);
if (name.startsWith("_"))
return name.tail(1);
return name;
}

void printDiagnosticArg(StringBuilder& sb, const CapabilityAtomSet atomSet)
{
bool isFirst = true;
for (auto atom : atomSet.removeImpliedAtoms())
{
CapabilityName formattedAtom = (CapabilityName)atom;
if (!isFirst)
sb << " + ";
sb << capabilityNameToStringWithoutPrefix(formattedAtom);
isFirst = false;
}
}

// Collection of stages which have same atom sets to compress reprisentation of atom and stage per target
struct CompressedCapabilitySet
{
bool isFirstSet = true;
for (auto& set : capSet.getAtomSets())
/// Collection of stages which have same atom sets to compress reprisentation of atom and stage: {vertex/fragment, ... }
struct StageAndAtomSet
{
CapabilityAtomSet stages;
CapabilityAtomSet atomsWithoutStage;
};

auto begin()
{
if (!isFirstSet)
return atomSetsOfTargets.begin();
}

/// Compress 1 capabilitySet into a reprisentation which merges stages that share all of their atoms for printing.
Dictionary<CapabilityAtom, List<StageAndAtomSet>> atomSetsOfTargets;
CompressedCapabilitySet(const CapabilitySet& capabilitySet)
{
for (auto& atomSet : capabilitySet.getAtomSets())
{
sb<< " | ";
auto target = getTargetAtomInSet(atomSet);

auto stageInSetAtom = getStageAtomInSet(atomSet);
CapabilityAtomSet stageInSet;
stageInSet.add((UInt)stageInSetAtom);

CapabilityAtomSet atomsWithoutStage;
CapabilityAtomSet::calcSubtract(atomsWithoutStage, atomSet, stageInSet);
if (!atomSetsOfTargets.containsKey(target))
{
atomSetsOfTargets[target].add({ stageInSet, atomsWithoutStage });
continue;
}

// try to find an equivlent atom set by iterating all of the same `atomSetsOfTarget[target]` and merge these 2 together.
auto& atomSetsOfTarget = atomSetsOfTargets[target];
for (auto& i : atomSetsOfTarget)
{
if (i.atomsWithoutStage.contains(atomsWithoutStage) && atomsWithoutStage.contains(i.atomsWithoutStage))
{
i.stages.add((UInt)stageInSetAtom);
}
}
}
bool isFirst = true;
for (auto atom : set)
for (auto& targetSets : atomSetsOfTargets)
for (auto& targetSet : targetSets.second)
targetSet.atomsWithoutStage = targetSet.atomsWithoutStage.removeImpliedAtoms();
}
};

void printDiagnosticArg(StringBuilder& sb, const CompressedCapabilitySet& capabilitySet)
{
////Secondly we will print our new list of atomSet's.
sb << "{";
bool firstSet = true;
for (auto targetSets : capabilitySet.atomSetsOfTargets)
{
if(!firstSet)
sb << " || ";
for (auto targetSet : targetSets.second)
{
CapabilityName formattedAtom = (CapabilityName)atom;
if (!isFirst)
bool firstStage = true;
for (auto stageAtom : targetSet.stages)
{
if (!firstStage)
sb << "/";
printDiagnosticArg(sb, (CapabilityName)stageAtom);
firstStage = false;
}
for (auto atom : targetSet.atomsWithoutStage)
{
sb << " + ";
printDiagnosticArg(sb, (CapabilityName)atom);
}
auto name = capabilityNameToString((CapabilityName)formattedAtom);
if (name.startsWith("_"))
name = name.tail(1);
sb << name;
isFirst = false;
}
isFirstSet = false;
firstSet = false;
}
sb << "}";
}

void printDiagnosticArg(StringBuilder& sb, const CapabilitySet& capabilitySet)
{
// Firstly we will compress the printing of capabilities such that any atomSet
// with different abstract atoms but equal non-abstract atoms will be bundled together.
if (capabilitySet.isInvalid() || capabilitySet.isEmpty())
{
sb << "{}";
return;
}
printDiagnosticArg(sb, CompressedCapabilitySet(capabilitySet));
}

void printDiagnosticArg(StringBuilder& sb, CapabilityAtom atom)
Expand All @@ -931,20 +1069,15 @@ void printDiagnosticArg(StringBuilder& sb, CapabilityAtom atom)

void printDiagnosticArg(StringBuilder& sb, CapabilityName name)
{
sb << _getInfo(name).name;
sb << capabilityNameToStringWithoutPrefix(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 << "}";
CapabilityAtomSet set;
for (auto i : list)
set.add((UInt)i);
printDiagnosticArg(sb, set.removeImpliedAtoms());
}


Expand Down
2 changes: 2 additions & 0 deletions source/slang/slang-capability.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ namespace Slang
struct CapabilityAtomSet : UIntSet
{
using UIntSet::UIntSet;

CapabilityAtomSet removeImpliedAtoms() const;
};

struct CapabilityTargetSet;
Expand Down
1 change: 1 addition & 0 deletions source/slang/slang-check-shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ namespace Slang
entryPointFuncDecl->loc,
Diagnostics::profileImplicitlyUpgraded,
Diagnostics::profileImplicitlyUpgradedRestrictive,
target->getOptionSet().getProfile().getName(),
addedAtoms.getElements<CapabilityAtom>());
}
}
Expand Down
4 changes: 2 additions & 2 deletions source/slang/slang-diagnostic-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -737,8 +737,8 @@ DIAGNOSTIC(41001, Error, recursiveType, "type '$0' contains cyclic reference to

DIAGNOSTIC(41010, Warning, missingReturn, "control flow may reach end of non-'void' function")
DIAGNOSTIC(41011, Error, profileIncompatibleWithTargetSwitch, "__target_switch has no compatable target with current profile '$0'")
DIAGNOSTIC(41012, Warning, profileImplicitlyUpgraded, "user set `profile` had an implicit upgrade applied to it, atoms added: '$0'")
DIAGNOSTIC(41012, Error, profileImplicitlyUpgradedRestrictive, "user set `profile` had an implicit upgrade applied to it, atoms added: '$0'")
DIAGNOSTIC(41012, Warning, profileImplicitlyUpgraded, "user set profile $0 had an implicit upgrade applied to it, atoms added: '$1'")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"shader '$0' uses additional capabilities that are not part of the specified profile '$1'. The profile setting is automatically updated to include these capabilities: '$2'"

DIAGNOSTIC(41012, Error, profileImplicitlyUpgradedRestrictive, "user set profile $0 had an implicit upgrade applied to it, atoms added: '$1'")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"shader '$0' uses capabilities that are not part of the specified profile '$1'. Missing capabilities are: '$2'"

DIAGNOSTIC(41015, Warning, usingUninitializedOut, "use of uninitialized out parameter '$0'")
DIAGNOSTIC(41016, Warning, usingUninitializedVariable, "use of uninitialized variable '$0'")
DIAGNOSTIC(41017, Warning, usingUninitializedGlobalVariable, "use of uninitialized global variable '$0'")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//TEST:SIMPLE(filecheck=CHECK): -target glsl -entry computeMain -stage compute -profile sm_5_0
//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target glsl -emit-spirv-directly -entry computeMain -stage compute -profile sm_5_0 -ignore-capabilities


// CHECK_IGNORE_CAPS-NOT: error 36107

// CHECK: error 36107
// CHECK-NOT: sm_6_0
// CHECK-NOT: sm_6_3
// CHECK-NOT: sm_6_4
// CHECK-SAME: vertex{{.*}}/{{.*}}fragment
// CHECK-SAME: sm_6_5

[numthreads(1,1,1)]
void computeMain()
{
WaveMultiPrefixProduct(1, 0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//TEST:SIMPLE(filecheck=SPIRV): -target spirv -emit-spirv-directly -entry computeMain -stage compute -profile sm_5_0
//TEST:SIMPLE(filecheck=GLSL): -target glsl -entry computeMain -stage compute -profile sm_5_0
//TEST:SIMPLE(filecheck=HLSL): -target hlsl -entry computeMain -stage compute -profile sm_5_0
//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target spirv -emit-spirv-directly -entry computeMain -stage compute -profile sm_5_0 -ignore-capabilities


// CHECK_IGNORE_CAPS-NOT: warning 41012

// SPIRV: warning 41012
// SPIRV-NOT: spirv_1_2
// SPIRV-NOT: spirv_1_3
// SPIRV-SAME: spvGroupNonUniformBallot

// GLSL: warning 41012
// GLSL-NOT: GLSL_400
// GLSL-NOT: GLSL_430
// GLSL-SAME: GL_KHR_shader_subgroup_ballot

// HLSL: warning 41012
// HLSL-NOT: sm_5_1
// HLSL-SAME: sm_6_0

[require(sm_6_0)]
[numthreads(1,1,1)]
void computeMain()
{
}
Loading