blob: 3f6b0ce3002635c3a6a46bb63e6321083026b6a7 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// //
// DxilSignatureElement.h //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// Class to pack HLSL signature element. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "dxc/HLSL/DxilPackSignatureElement.h"
#include "dxc/DXIL/DxilSigPoint.h"
#include "dxc/DXIL/DxilSignature.h"
#include "dxc/HLSL/DxilSignatureAllocator.h"
#include "dxc/Support/Global.h"
using namespace hlsl;
using namespace llvm;
namespace hlsl {
unsigned PackDxilSignature(DxilSignature &sig, DXIL::PackingStrategy packing) {
unsigned rowsUsed = 0;
bool bUseMinPrecision = sig.UseMinPrecision();
// Transfer to elements derived from DxilSignatureAllocator::PackElement
std::vector<DxilPackElement> packElements;
for (auto &SE : sig.GetElements()) {
if (DxilSignature::ShouldBeAllocated(SE.get()->GetInterpretation()))
packElements.emplace_back(SE.get(), bUseMinPrecision);
}
DXIL::SigPointKind Kind = sig.GetSigPointKind();
if (Kind == DXIL::SigPointKind::GSOut) {
// Special case due to support for multiple streams
DxilSignatureAllocator alloc[4] = {{32, bUseMinPrecision},
{32, bUseMinPrecision},
{32, bUseMinPrecision},
{32, bUseMinPrecision}};
std::vector<DxilSignatureAllocator::PackElement *> 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(Kind);
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, bUseMinPrecision);
std::vector<DxilSignatureAllocator::PackElement *> 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;
}
} // namespace hlsl
#include "dxc/HLSL/DxilSignatureAllocator.inl"
#include <algorithm>