|
@@ -37,6 +37,10 @@ struct ComponentMask : public PSVComponentMask {
|
|
|
}
|
|
|
return *this;
|
|
|
}
|
|
|
+ ComponentMask &operator=(const ComponentMask &other) {
|
|
|
+ *this = (const PSVComponentMask &)other;
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
ComponentMask &operator|=(const PSVComponentMask &other) {
|
|
|
NumVectors = std::max(NumVectors, other.NumVectors);
|
|
|
PSVComponentMask::operator|=(other);
|
|
@@ -94,13 +98,19 @@ static void AddViewIDElements(ElementVec &outElements,
|
|
|
if (adding) {
|
|
|
uint32_t componentIndex = (E.GetStartRow() + row) * 4 + E.GetStartCol() + col;
|
|
|
DxilSignatureAllocator::DummyElement NE(numElements);
|
|
|
- NE.rows = bDynIndex ? E.GetRows() : 1;
|
|
|
- if (mask.Get(componentIndex)) {
|
|
|
- NE.rows *= viewIDCount;
|
|
|
- }
|
|
|
NE.kind = E.kind;
|
|
|
NE.interpolation = E.interpolation;
|
|
|
NE.interpretation = E.interpretation;
|
|
|
+ NE.rows = bDynIndex ? E.GetRows() : 1;
|
|
|
+ for (uint32_t indexedRow = 0; indexedRow < NE.rows; indexedRow++) {
|
|
|
+ if (mask.Get(componentIndex + (4 * indexedRow))) {
|
|
|
+ if (E.GetKind() == DXIL::SemanticKind::ClipDistance || E.GetKind() == DXIL::SemanticKind::CullDistance) {
|
|
|
+ NE.kind = DXIL::SemanticKind::Arbitrary;
|
|
|
+ }
|
|
|
+ NE.rows *= viewIDCount;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
outElements.push_back(NE);
|
|
|
}
|
|
|
numElements++;
|
|
@@ -108,7 +118,7 @@ static void AddViewIDElements(ElementVec &outElements,
|
|
|
}
|
|
|
}
|
|
|
if (!adding)
|
|
|
- outElements.resize(numElements);
|
|
|
+ outElements.reserve(numElements);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -118,6 +128,7 @@ static bool CheckFit(ElementVec &elements) {
|
|
|
for (auto &E : elements)
|
|
|
packElements.push_back(&E);
|
|
|
DxilSignatureAllocator alloc(32);
|
|
|
+ alloc.SetIgnoreIndexing(true);
|
|
|
alloc.PackOptimized(packElements, 0, 32);
|
|
|
for (auto &E : elements) {
|
|
|
if (!E.IsAllocated())
|
|
@@ -126,6 +137,13 @@ static bool CheckFit(ElementVec &elements) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static bool CheckMaxVertexCount(const ElementVec &elements, unsigned maxVertexCount) {
|
|
|
+ unsigned numComponents = 0;
|
|
|
+ for (auto &E : elements)
|
|
|
+ numComponents += E.GetRows() * E.GetCols();
|
|
|
+ return numComponents <= 1024 && maxVertexCount <= 1024 && numComponents * maxVertexCount <= 1024;
|
|
|
+}
|
|
|
+
|
|
|
static bool MergeElements(const ElementVec &priorElements,
|
|
|
ElementVec &inputElements,
|
|
|
uint32_t &numVectors,
|
|
@@ -182,6 +200,21 @@ static void PropagateMask(const ComponentMask &priorMask,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+bool DetectViewIDDependentTessFactor(const ElementVec &pcElements, ComponentMask &mask) {
|
|
|
+ for (auto &E : pcElements) {
|
|
|
+ if (E.GetKind() == DXIL::SemanticKind::TessFactor || E.GetKind() == DXIL::SemanticKind::InsideTessFactor) {
|
|
|
+ for (unsigned row = 0; row < E.GetRows(); row++) {
|
|
|
+ for (unsigned col = 0; col < E.GetCols(); col++) {
|
|
|
+ uint32_t componentIndex = (E.GetStartRow() + row) * 4 + E.GetStartCol() + col;
|
|
|
+ if (mask.Get(componentIndex))
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
class ViewIDValidator_impl : public hlsl::ViewIDValidator {
|
|
|
ComponentMask m_PriorOutputMask;
|
|
|
ComponentMask m_PriorPCMask;
|
|
@@ -190,6 +223,13 @@ class ViewIDValidator_impl : public hlsl::ViewIDValidator {
|
|
|
unsigned m_ViewIDCount;
|
|
|
unsigned m_GSRastStreamIndex;
|
|
|
|
|
|
+ void ClearPriorState() {
|
|
|
+ m_PriorOutputMask = ComponentMask();
|
|
|
+ m_PriorPCMask = ComponentMask();
|
|
|
+ m_PriorOutputSignature.clear();
|
|
|
+ m_PriorPCSignature.clear();
|
|
|
+ }
|
|
|
+
|
|
|
public:
|
|
|
ViewIDValidator_impl(unsigned viewIDCount, unsigned gsRastStreamIndex)
|
|
|
: m_PriorOutputMask(),
|
|
@@ -199,6 +239,7 @@ public:
|
|
|
virtual ~ViewIDValidator_impl() {}
|
|
|
__override Result ValidateStage(const DxilPipelineStateValidation &PSV,
|
|
|
bool bFinalStage,
|
|
|
+ bool bExpandInputOnly,
|
|
|
unsigned &mismatchElementId) {
|
|
|
if (!PSV.GetPSVRuntimeInfo0())
|
|
|
return Result::InvalidPSV;
|
|
@@ -207,6 +248,9 @@ public:
|
|
|
|
|
|
switch (PSV.GetShaderKind()) {
|
|
|
case PSVShaderKind::Vertex: {
|
|
|
+ if (bExpandInputOnly)
|
|
|
+ return Result::InvalidUsage;
|
|
|
+
|
|
|
// Initialize mask with direct ViewID dependent outputs
|
|
|
ComponentMask mask(PSV.GetViewIDOutputMask(0));
|
|
|
|
|
@@ -239,14 +283,6 @@ public:
|
|
|
[&](unsigned i) -> PSVSignatureElement {
|
|
|
return PSV.GetSignatureElement(PSV.GetInputElement0(i));
|
|
|
});
|
|
|
- CopyElements( outSig, DXIL::SigPointKind::HSCPOut, PSV.GetSigOutputElements(), 0,
|
|
|
- [&](unsigned i) -> PSVSignatureElement {
|
|
|
- return PSV.GetSignatureElement(PSV.GetOutputElement0(i));
|
|
|
- });
|
|
|
- CopyElements( pcSig, DXIL::SigPointKind::PCOut, PSV.GetSigPatchConstantElements(), 0,
|
|
|
- [&](unsigned i) -> PSVSignatureElement {
|
|
|
- return PSV.GetSignatureElement(PSV.GetPatchConstantElement0(i));
|
|
|
- });
|
|
|
|
|
|
// Merge prior and input signatures, update prior mask size if necessary
|
|
|
if (!MergeElements(m_PriorOutputSignature, inSig, m_PriorOutputMask.NumVectors, mismatchElementId))
|
|
@@ -260,6 +296,20 @@ public:
|
|
|
if (!CheckFit(viewIDSig))
|
|
|
return Result::InsufficientSpace;
|
|
|
|
|
|
+ if (bExpandInputOnly) {
|
|
|
+ ClearPriorState();
|
|
|
+ return Result::Success;
|
|
|
+ }
|
|
|
+
|
|
|
+ CopyElements(outSig, DXIL::SigPointKind::HSCPOut, PSV.GetSigOutputElements(), 0,
|
|
|
+ [&](unsigned i) -> PSVSignatureElement {
|
|
|
+ return PSV.GetSignatureElement(PSV.GetOutputElement0(i));
|
|
|
+ });
|
|
|
+ CopyElements(pcSig, DXIL::SigPointKind::PCOut, PSV.GetSigPatchConstantElements(), 0,
|
|
|
+ [&](unsigned i) -> PSVSignatureElement {
|
|
|
+ return PSV.GetSignatureElement(PSV.GetPatchConstantElement0(i));
|
|
|
+ });
|
|
|
+
|
|
|
// Propagate prior mask through input-output dependencies
|
|
|
if (PSV.GetInputToOutputTable(0).IsValid()) {
|
|
|
PropagateMask(m_PriorOutputMask, inSig, outputMask,
|
|
@@ -278,6 +328,10 @@ public:
|
|
|
m_PriorOutputSignature = std::move(outSig);
|
|
|
m_PriorPCSignature = std::move(pcSig);
|
|
|
|
|
|
+ if (DetectViewIDDependentTessFactor(pcSig, pcMask)) {
|
|
|
+ return Result::SuccessWithViewIDDependentTessFactor;
|
|
|
+ }
|
|
|
+
|
|
|
break;
|
|
|
}
|
|
|
case PSVShaderKind::Domain: {
|
|
@@ -294,10 +348,6 @@ public:
|
|
|
[&](unsigned i) -> PSVSignatureElement {
|
|
|
return PSV.GetSignatureElement(PSV.GetPatchConstantElement0(i));
|
|
|
});
|
|
|
- CopyElements( outSig, DXIL::SigPointKind::DSOut, PSV.GetSigOutputElements(), 0,
|
|
|
- [&](unsigned i) -> PSVSignatureElement {
|
|
|
- return PSV.GetSignatureElement(PSV.GetOutputElement0(i));
|
|
|
- });
|
|
|
|
|
|
// Merge prior and input signatures, update prior mask size if necessary
|
|
|
if (!MergeElements(m_PriorOutputSignature, inSig, m_PriorOutputMask.NumVectors, mismatchElementId))
|
|
@@ -325,6 +375,16 @@ public:
|
|
|
return Result::InsufficientPCSpace;
|
|
|
}
|
|
|
|
|
|
+ if (bExpandInputOnly) {
|
|
|
+ ClearPriorState();
|
|
|
+ return Result::Success;
|
|
|
+ }
|
|
|
+
|
|
|
+ CopyElements(outSig, DXIL::SigPointKind::DSOut, PSV.GetSigOutputElements(), 0,
|
|
|
+ [&](unsigned i) -> PSVSignatureElement {
|
|
|
+ return PSV.GetSignatureElement(PSV.GetOutputElement0(i));
|
|
|
+ });
|
|
|
+
|
|
|
// Propagate prior mask through input-output dependencies
|
|
|
if (PSV.GetInputToOutputTable(0).IsValid()) {
|
|
|
PropagateMask(m_PriorOutputMask, inSig, mask,
|
|
@@ -346,19 +406,12 @@ public:
|
|
|
break;
|
|
|
}
|
|
|
case PSVShaderKind::Geometry: {
|
|
|
- // Initialize mask with direct ViewID dependent outputs
|
|
|
- ComponentMask mask(PSV.GetViewIDOutputMask(m_GSRastStreamIndex));
|
|
|
-
|
|
|
// capture signatures
|
|
|
- ElementVec inSig, outSig;
|
|
|
+ ElementVec inSig, outSig[4];
|
|
|
CopyElements( inSig, DXIL::SigPointKind::GSVIn, PSV.GetSigInputElements(), 0,
|
|
|
[&](unsigned i) -> PSVSignatureElement {
|
|
|
return PSV.GetSignatureElement(PSV.GetInputElement0(i));
|
|
|
});
|
|
|
- CopyElements( outSig, DXIL::SigPointKind::GSOut, PSV.GetSigOutputElements(), m_GSRastStreamIndex,
|
|
|
- [&](unsigned i) -> PSVSignatureElement {
|
|
|
- return PSV.GetSignatureElement(PSV.GetOutputElement0(i));
|
|
|
- });
|
|
|
|
|
|
// Merge prior and input signatures, update prior mask size if necessary
|
|
|
if (!MergeElements(m_PriorOutputSignature, inSig, m_PriorOutputMask.NumVectors, mismatchElementId))
|
|
@@ -372,19 +425,52 @@ public:
|
|
|
if (!CheckFit(viewIDSig))
|
|
|
return Result::InsufficientSpace;
|
|
|
|
|
|
- // Propagate prior mask through input-output dependencies
|
|
|
- if (PSV.GetInputToOutputTable(0).IsValid()) {
|
|
|
- PropagateMask(m_PriorOutputMask, inSig, mask,
|
|
|
- [&](unsigned i) -> PSVComponentMask { return PSV.GetInputToOutputTable(m_GSRastStreamIndex).GetMaskForInput(i); });
|
|
|
+ if (bExpandInputOnly) {
|
|
|
+ ClearPriorState();
|
|
|
+ return Result::Success;
|
|
|
}
|
|
|
|
|
|
- // Copy mask to prior mask
|
|
|
- m_PriorOutputMask = mask;
|
|
|
+ for (unsigned streamIndex = 0; streamIndex < 4; streamIndex++) {
|
|
|
+ // Initialize mask with direct ViewID dependent outputs
|
|
|
+ ComponentMask mask(PSV.GetViewIDOutputMask(streamIndex));
|
|
|
|
|
|
- // Capture output signature for next stage
|
|
|
- m_PriorOutputSignature = std::move(outSig);
|
|
|
+ CopyElements( outSig[streamIndex], DXIL::SigPointKind::GSOut, PSV.GetSigOutputElements(), streamIndex,
|
|
|
+ [&](unsigned i) -> PSVSignatureElement {
|
|
|
+ return PSV.GetSignatureElement(PSV.GetOutputElement0(i));
|
|
|
+ });
|
|
|
|
|
|
- break;
|
|
|
+ if (!outSig[streamIndex].empty()) {
|
|
|
+ // Propagate prior mask through input-output dependencies
|
|
|
+ if (PSV.GetInputToOutputTable(streamIndex).IsValid()) {
|
|
|
+ PropagateMask(m_PriorOutputMask, inSig, mask,
|
|
|
+ [&](unsigned i) -> PSVComponentMask { return PSV.GetInputToOutputTable(streamIndex).GetMaskForInput(i); });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create new version with ViewID elements from prior signature
|
|
|
+ ElementVec viewIDSig;
|
|
|
+ AddViewIDElements(viewIDSig, outSig[streamIndex], mask, m_ViewIDCount);
|
|
|
+
|
|
|
+ // Verify fit
|
|
|
+ if (!CheckMaxVertexCount(viewIDSig, PSV.GetPSVRuntimeInfo1()->MaxVertexCount))
|
|
|
+ return Result::InsufficientSpace;
|
|
|
+ if (!CheckFit(viewIDSig))
|
|
|
+ return Result::InsufficientSpace;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Capture this mask for the next stage
|
|
|
+ if (m_GSRastStreamIndex == streamIndex)
|
|
|
+ m_PriorOutputMask = mask;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m_GSRastStreamIndex < 4 && !bFinalStage) {
|
|
|
+ m_PriorOutputSignature = std::move(outSig[m_GSRastStreamIndex]);
|
|
|
+ } else {
|
|
|
+ ClearPriorState();
|
|
|
+ if (!bFinalStage)
|
|
|
+ return Result::InvalidUsage;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Result::Success;
|
|
|
}
|
|
|
case PSVShaderKind::Pixel: {
|
|
|
// capture signatures
|