/////////////////////////////////////////////////////////////////////////////// // // // DxilSignature.cpp // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // /////////////////////////////////////////////////////////////////////////////// #include "dxc/Support/Global.h" #include "dxc/HLSL/DxilSignature.h" #include "dxc/HLSL/DxilSignatureAllocator.h" #include "dxc/HLSL/DxilSigPoint.h" #include "llvm/ADT/STLExtras.h" using std::vector; using std::unique_ptr; namespace hlsl { //------------------------------------------------------------------------------ // // Singnature methods. // DxilSignature::DxilSignature(DXIL::ShaderKind shaderKind, DXIL::SignatureKind sigKind, bool useMinPrecision) : m_sigPointKind(SigPoint::GetKind(shaderKind, sigKind, /*isPatchConstantFunction*/ false, /*isSpecialInput*/ false)), m_UseMinPrecision(useMinPrecision) {} DxilSignature::DxilSignature(DXIL::SigPointKind sigPointKind) : m_sigPointKind(sigPointKind) {} DxilSignature::DxilSignature(const DxilSignature &src) : m_sigPointKind(src.m_sigPointKind) { const bool bSetID = false; for (auto &Elt : src.GetElements()) { std::unique_ptr newElt = CreateElement(); newElt->Initialize(Elt->GetName(), Elt->GetCompType(), Elt->GetInterpolationMode()->GetKind(), Elt->GetRows(), Elt->GetCols(), Elt->GetStartRow(), Elt->GetStartCol(), Elt->GetID(), Elt->GetSemanticIndexVec()); AppendElement(std::move(newElt), bSetID); } } DxilSignature::~DxilSignature() { } bool DxilSignature::IsInput() const { return SigPoint::GetSigPoint(m_sigPointKind)->IsInput(); } bool DxilSignature::IsOutput() const { return SigPoint::GetSigPoint(m_sigPointKind)->IsOutput(); } unique_ptr DxilSignature::CreateElement() { return llvm::make_unique(m_sigPointKind); } unsigned DxilSignature::AppendElement(std::unique_ptr pSE, bool bSetID) { DXASSERT_NOMSG((unsigned)m_Elements.size() < UINT_MAX); unsigned Id = (unsigned)m_Elements.size(); if (bSetID) { pSE->SetID(Id); } m_Elements.emplace_back(std::move(pSE)); return Id; } DxilSignatureElement &DxilSignature::GetElement(unsigned idx) { return *m_Elements[idx]; } const DxilSignatureElement &DxilSignature::GetElement(unsigned idx) const { return *m_Elements[idx]; } const std::vector > &DxilSignature::GetElements() const { return m_Elements; } namespace { static bool ShouldBeAllocated(const DxilSignatureElement *SE) { DXIL::SemanticInterpretationKind I = SE->GetInterpretation(); switch (I) { case DXIL::SemanticInterpretationKind::NA: case DXIL::SemanticInterpretationKind::NotInSig: case DXIL::SemanticInterpretationKind::NotPacked: case DXIL::SemanticInterpretationKind::Shadow: return false; default: break; } return true; } } // anonymous namespace bool DxilSignature::IsFullyAllocated() const { for (auto &SE : m_Elements) { if (!ShouldBeAllocated(SE.get())) continue; if (!SE->IsAllocated()) return false; } return true; } unsigned DxilSignature::NumVectorsUsed(unsigned streamIndex) const { unsigned NumVectors = 0; for (auto &SE : m_Elements) { if (SE->IsAllocated() && SE->GetOutputStream() == streamIndex) NumVectors = std::max(NumVectors, (unsigned)SE->GetStartRow() + SE->GetRows()); } return NumVectors; } unsigned DxilSignature::PackElements(DXIL::PackingStrategy packing) { unsigned rowsUsed = 0; // Transfer to elements derived from DxilSignatureAllocator::PackElement std::vector packElements; for (auto &SE : m_Elements) { if (ShouldBeAllocated(SE.get())) packElements.emplace_back(SE.get(), m_UseMinPrecision); } if (m_sigPointKind == DXIL::SigPointKind::GSOut) { // Special case due to support for multiple streams DxilSignatureAllocator alloc[4] = {{32, UseMinPrecision()}, {32, UseMinPrecision()}, {32, UseMinPrecision()}, {32, UseMinPrecision()}}; std::vector elements[4]; for (auto &SE : packElements) { elements[SE.Get()->GetOutputStream()].push_back(&SE); } for (unsigned i = 0; i < 4; ++i) { if (!elements[i].empty()) { unsigned streamRowsUsed = 0; switch (packing) { case DXIL::PackingStrategy::PrefixStable: streamRowsUsed = alloc[i].PackPrefixStable(elements[i], 0, 32); break; case DXIL::PackingStrategy::Optimized: streamRowsUsed = alloc[i].PackOptimized(elements[i], 0, 32); break; default: DXASSERT(false, "otherwise, invalid packing strategy supplied"); } if (streamRowsUsed > rowsUsed) rowsUsed = streamRowsUsed; } } // rowsUsed isn't really meaningful in this case. return rowsUsed; } const SigPoint *SP = SigPoint::GetSigPoint(m_sigPointKind); DXIL::PackingKind PK = SP->GetPackingKind(); switch (PK) { case DXIL::PackingKind::None: // no packing. break; case DXIL::PackingKind::InputAssembler: // incrementally assign each element that belongs in the signature to the start of the next free row for (auto &SE : packElements) { SE.SetLocation(rowsUsed, 0); rowsUsed += SE.GetRows(); } break; case DXIL::PackingKind::Vertex: case DXIL::PackingKind::PatchConstant: { DxilSignatureAllocator alloc(32, UseMinPrecision()); std::vector elements; elements.reserve(packElements.size()); for (auto &SE : packElements){ elements.push_back(&SE); } switch (packing) { case DXIL::PackingStrategy::PrefixStable: rowsUsed = alloc.PackPrefixStable(elements, 0, 32); break; case DXIL::PackingStrategy::Optimized: rowsUsed = alloc.PackOptimized(elements, 0, 32); break; default: DXASSERT(false, "otherwise, invalid packing strategy supplied"); } } break; case DXIL::PackingKind::Target: // for SV_Target, assign rows according to semantic index, the rest are unassigned (-1) // Note: Overlapping semantic indices should be checked elsewhere for (auto &SE : packElements) { if (SE.GetKind() != DXIL::SemanticKind::Target) continue; unsigned row = SE.Get()->GetSemanticStartIndex(); SE.SetLocation(row, 0); DXASSERT(SE.GetRows() == 1, "otherwise, SV_Target output not broken into separate rows earlier"); row += SE.GetRows(); if (rowsUsed < row) rowsUsed = row; } break; case DXIL::PackingKind::Invalid: default: DXASSERT(false, "unexpected PackingKind."); } return rowsUsed; } //------------------------------------------------------------------------------ // // EntrySingnature methods. // DxilEntrySignature::DxilEntrySignature(const DxilEntrySignature &src) : InputSignature(src.InputSignature), OutputSignature(src.OutputSignature), PatchConstantSignature(src.PatchConstantSignature) {} } // namespace hlsl #include #include "dxc/HLSL/DxilSignatureAllocator.inl" #include "dxc/HLSL/DxilSigPoint.inl" #include "dxc/HLSL/DxilPipelineStateValidation.h" #include #include "dxc/HLSL/ViewIDPipelineValidation.inl"