Skip to content

Commit f45b645

Browse files
Merge pull request #1697 from vsg-dev/GraphicsPipelineConfiguratorCompareFixes
Refactor how GraphicsPipelineCongfigurator::compare() handles the shaderHints->defines and descriptorConfigurator->defines together to avoid failure to match compatible configurations.
2 parents 03f8473 + ba3ee37 commit f45b645

3 files changed

Lines changed: 104 additions & 6 deletions

File tree

include/vsg/state/ShaderModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ namespace vsg
5959

6060
public:
6161
ref_ptr<Object> clone(const CopyOp& copyop = {}) const override { return ShaderCompileSettings::create(*this, copyop); }
62+
63+
virtual int compare_except_defines(const Object& rhs_object) const;
6264
int compare(const Object& rhs_object) const override;
6365

6466
void read(Input& input) override;

src/vsg/state/ShaderModule.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ ShaderCompileSettings::ShaderCompileSettings(const ShaderCompileSettings& rhs, c
4040
{
4141
}
4242

43-
int ShaderCompileSettings::compare(const Object& rhs_object) const
43+
int ShaderCompileSettings::compare_except_defines(const Object& rhs_object) const
4444
{
4545
int result = Object::compare(rhs_object);
4646
if (result != 0) return result;
@@ -54,7 +54,15 @@ int ShaderCompileSettings::compare(const Object& rhs_object) const
5454
if ((result = compare_value(target, rhs.target))) return result;
5555
if ((result = compare_value(forwardCompatible, rhs.forwardCompatible))) return result;
5656
if ((result = compare_value(generateDebugInfo, rhs.generateDebugInfo))) return result;
57-
if ((result = compare_value(optimize, rhs.optimize))) return result;
57+
return compare_value(optimize, rhs.optimize);
58+
}
59+
60+
int ShaderCompileSettings::compare(const Object& rhs_object) const
61+
{
62+
int result = compare_except_defines(rhs_object);
63+
if (result != 0) return result;
64+
65+
const auto& rhs = static_cast<decltype(*this)>(rhs_object);
5866
return compare_container(defines, rhs.defines);
5967
}
6068

src/vsg/utils/GraphicsPipelineConfigurator.cpp

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -535,8 +535,98 @@ int GraphicsPipelineConfigurator::compare(const Object& rhs_object) const
535535
if ((result = compare_value(baseAttributeBinding, rhs.baseAttributeBinding))) return result;
536536
if ((result = compare_pointer(shaderSet, rhs.shaderSet))) return result;
537537

538-
if ((result = compare_pointer(shaderHints, rhs.shaderHints))) return result;
539-
if ((result = compare_pointer_container(inheritedState, rhs.inheritedState))) return result;
538+
//
539+
// defines settings for ShaderHints may not yet be in final state, so comparing them between compatible GraphicsPipelineConfigurator
540+
// objects can lead is not returning a match when just comparing shaderHint->defines.
541+
// To resolve this do the shint hint compare wihtout the defines, and then do the comparison of defines
542+
// by handling both the respective descriptorConfigurator->defines and shaderHints->defines when comparing to the rhs.
543+
//
544+
// The compare_shaderHints, IteratorPair and Iterator structs all exist in service of this mutliset comparison.
545+
//
546+
547+
auto compare_shaderHints = [](const ref_ptr<ShaderCompileSettings>& lsh, const ref_ptr<ShaderCompileSettings>& rsh) -> int
548+
{
549+
if (lsh == rsh) return 0;
550+
return lsh ? (rsh ? lsh->compare_except_defines(*rsh) : 1) : (rsh ? -1 : 0);
551+
};
552+
553+
if ((result = compare_shaderHints(shaderHints, rhs.shaderHints))) return result;
554+
555+
struct IteratorPair
556+
{
557+
using iterator = std::set<std::string>::const_iterator;
558+
iterator itr;
559+
iterator end;
560+
561+
explicit IteratorPair(const std::set<std::string>& values) : itr(values.begin()), end(values.end()) {}
562+
563+
bool valid() const { return itr != end; }
564+
};
565+
566+
struct Iterator
567+
{
568+
IteratorPair lhs;
569+
IteratorPair rhs;
570+
571+
explicit Iterator(IteratorPair in_lhs, IteratorPair in_rhs) : lhs(in_lhs), rhs(in_rhs) {}
572+
573+
bool valid() const { return lhs.valid() || rhs.valid(); }
574+
575+
/// only call when valid() return true
576+
const std::string& value() const
577+
{
578+
if (lhs.valid())
579+
{
580+
if (rhs.valid())
581+
{
582+
if (*lhs.itr < *rhs.itr) return *lhs.itr;
583+
else if (*rhs.itr < *lhs.itr ) return *rhs.itr;
584+
else { return *rhs.itr; }
585+
}
586+
else return *lhs.itr;
587+
}
588+
else return *rhs.itr;
589+
}
590+
591+
bool advance()
592+
{
593+
if (lhs.valid())
594+
{
595+
if (rhs.valid())
596+
{
597+
if (*lhs.itr < *rhs.itr) lhs.itr++;
598+
else if (*rhs.itr < *lhs.itr) rhs.itr++;
599+
else { ++lhs.itr; ++rhs.itr; }
600+
}
601+
else lhs.itr++;
602+
}
603+
else if (rhs.valid()) rhs.itr++;
604+
605+
return valid();
606+
}
607+
};
608+
609+
auto local_compare = [](Iterator ilhs, Iterator irhs) -> int
610+
{
611+
while(ilhs.valid() && irhs.valid())
612+
{
613+
const auto& lhs_value = ilhs.value();
614+
const auto& rhs_value = irhs.value();
615+
if (lhs_value < rhs_value) return -1;
616+
else if (lhs_value > rhs_value) return 1;
617+
618+
ilhs.advance();
619+
irhs.advance();
620+
}
621+
622+
if (ilhs.valid()) return 1;
623+
return irhs.valid() ? -1 : 0;
624+
};
625+
626+
result = local_compare(Iterator(IteratorPair(descriptorConfigurator->defines), IteratorPair(shaderHints->defines)),
627+
Iterator(IteratorPair(rhs.descriptorConfigurator->defines), IteratorPair(rhs.shaderHints->defines)));
628+
629+
if (result) return result;
540630

541631
return compare_pointer(descriptorConfigurator, rhs.descriptorConfigurator);
542632
}
@@ -612,8 +702,6 @@ void GraphicsPipelineConfigurator::_assignInheritedSets()
612702

613703
void GraphicsPipelineConfigurator::init()
614704
{
615-
// if (!descriptorConfigurator) descriptorConfigurator = DescriptorConfigurator::create(shaderSet);
616-
617705
_assignInheritedSets();
618706

619707
if (descriptorConfigurator)

0 commit comments

Comments
 (0)