Dedup semantic names in IO signature parts for valver 1.7 (#4406)
Create new NameOffsetMap that uses StringRef to prevent identical strings from being duplicated. Old behavior is maintained when earlier validator version set by using a *_nodedup map that continues to use a pointer to allow duplicates as previous validators did.
This commit is contained in:
Родитель
88d88ae365
Коммит
e138888302
|
@ -119,6 +119,7 @@ private:
|
||||||
FileRunCommandResult RunDxc(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
FileRunCommandResult RunDxc(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
||||||
FileRunCommandResult RunDxv(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
FileRunCommandResult RunDxv(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
||||||
FileRunCommandResult RunOpt(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
FileRunCommandResult RunOpt(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
||||||
|
FileRunCommandResult RunListParts(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
||||||
FileRunCommandResult RunD3DReflect(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
FileRunCommandResult RunD3DReflect(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
||||||
FileRunCommandResult RunDxr(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
FileRunCommandResult RunDxr(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
||||||
FileRunCommandResult RunLink(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
FileRunCommandResult RunLink(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior);
|
||||||
|
|
|
@ -179,11 +179,14 @@ private:
|
||||||
bool m_isInput;
|
bool m_isInput;
|
||||||
bool m_useMinPrecision;
|
bool m_useMinPrecision;
|
||||||
bool m_bCompat_1_4;
|
bool m_bCompat_1_4;
|
||||||
bool m_bUnaligned; // unaligned size for < 1.7
|
bool m_bCompat_1_6; // unaligned size, no dedup for < 1.7
|
||||||
size_t m_fixedSize;
|
size_t m_fixedSize;
|
||||||
typedef std::pair<const char *, uint32_t> NameOffsetPair;
|
typedef std::pair<const char *, uint32_t> NameOffsetPair_nodedup;
|
||||||
typedef llvm::SmallMapVector<const char *, uint32_t, 8> NameOffsetMap;
|
typedef llvm::SmallMapVector<const char *, uint32_t, 8> NameOffsetMap_nodedup;
|
||||||
|
typedef std::pair<llvm::StringRef, uint32_t> NameOffsetPair;
|
||||||
|
typedef llvm::SmallMapVector<llvm::StringRef, uint32_t, 8> NameOffsetMap;
|
||||||
uint32_t m_lastOffset;
|
uint32_t m_lastOffset;
|
||||||
|
NameOffsetMap_nodedup m_semanticNameOffsets_nodedup;
|
||||||
NameOffsetMap m_semanticNameOffsets;
|
NameOffsetMap m_semanticNameOffsets;
|
||||||
unsigned m_paramCount;
|
unsigned m_paramCount;
|
||||||
|
|
||||||
|
@ -193,14 +196,31 @@ private:
|
||||||
return pElement->GetName();
|
return pElement->GetName();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetSemanticOffset(const hlsl::DxilSignatureElement *pElement) {
|
uint32_t GetSemanticOffset_nodedup(const hlsl::DxilSignatureElement *pElement) {
|
||||||
const char *pName = GetSemanticName(pElement);
|
const char *pName = GetSemanticName(pElement);
|
||||||
NameOffsetMap::iterator nameOffset = m_semanticNameOffsets.find(pName);
|
NameOffsetMap_nodedup::iterator nameOffset = m_semanticNameOffsets_nodedup.find(pName);
|
||||||
|
uint32_t result;
|
||||||
|
if (nameOffset == m_semanticNameOffsets_nodedup.end()) {
|
||||||
|
result = m_lastOffset;
|
||||||
|
m_semanticNameOffsets_nodedup.insert(NameOffsetPair_nodedup(pName, result));
|
||||||
|
m_lastOffset += strlen(pName) + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = nameOffset->second;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint32_t GetSemanticOffset(const hlsl::DxilSignatureElement *pElement) {
|
||||||
|
if (m_bCompat_1_6)
|
||||||
|
return GetSemanticOffset_nodedup(pElement);
|
||||||
|
|
||||||
|
StringRef name = GetSemanticName(pElement);
|
||||||
|
NameOffsetMap::iterator nameOffset = m_semanticNameOffsets.find(name);
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
if (nameOffset == m_semanticNameOffsets.end()) {
|
if (nameOffset == m_semanticNameOffsets.end()) {
|
||||||
result = m_lastOffset;
|
result = m_lastOffset;
|
||||||
m_semanticNameOffsets.insert(NameOffsetPair(pName, result));
|
m_semanticNameOffsets.insert(NameOffsetPair(name, result));
|
||||||
m_lastOffset += strlen(pName) + 1;
|
m_lastOffset += name.size() + 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = nameOffset->second;
|
result = nameOffset->second;
|
||||||
|
@ -285,16 +305,16 @@ public:
|
||||||
DXIL::TessellatorDomain domain,
|
DXIL::TessellatorDomain domain,
|
||||||
bool isInput, bool UseMinPrecision,
|
bool isInput, bool UseMinPrecision,
|
||||||
bool bCompat_1_4,
|
bool bCompat_1_4,
|
||||||
bool bUnaligned)
|
bool bCompat_1_6)
|
||||||
: m_signature(signature), m_domain(domain),
|
: m_signature(signature), m_domain(domain),
|
||||||
m_isInput(isInput), m_useMinPrecision(UseMinPrecision),
|
m_isInput(isInput), m_useMinPrecision(UseMinPrecision),
|
||||||
m_bCompat_1_4(bCompat_1_4),
|
m_bCompat_1_4(bCompat_1_4),
|
||||||
m_bUnaligned(bUnaligned) {
|
m_bCompat_1_6(bCompat_1_6) {
|
||||||
calcSizes();
|
calcSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size() const override {
|
uint32_t size() const override {
|
||||||
if (m_bUnaligned)
|
if (m_bCompat_1_6)
|
||||||
return m_lastOffset;
|
return m_lastOffset;
|
||||||
else
|
else
|
||||||
return PSVALIGN4(m_lastOffset);
|
return PSVALIGN4(m_lastOffset);
|
||||||
|
@ -325,19 +345,23 @@ public:
|
||||||
|
|
||||||
// Write strings in the offset order.
|
// Write strings in the offset order.
|
||||||
std::vector<NameOffsetPair> ordered;
|
std::vector<NameOffsetPair> ordered;
|
||||||
ordered.assign(m_semanticNameOffsets.begin(), m_semanticNameOffsets.end());
|
if (m_bCompat_1_6) {
|
||||||
|
ordered.assign(m_semanticNameOffsets_nodedup.begin(), m_semanticNameOffsets_nodedup.end());
|
||||||
|
} else {
|
||||||
|
ordered.assign(m_semanticNameOffsets.begin(), m_semanticNameOffsets.end());
|
||||||
|
}
|
||||||
std::sort(ordered.begin(), ordered.end(), sort_second<NameOffsetPair>());
|
std::sort(ordered.begin(), ordered.end(), sort_second<NameOffsetPair>());
|
||||||
for (size_t i = 0; i < ordered.size(); ++i) {
|
for (size_t i = 0; i < ordered.size(); ++i) {
|
||||||
const char *pName = ordered[i].first;
|
StringRef name = ordered[i].first;
|
||||||
ULONG cbWritten;
|
ULONG cbWritten;
|
||||||
UINT64 offsetPos = pStream->GetPosition();
|
UINT64 offsetPos = pStream->GetPosition();
|
||||||
DXASSERT_LOCALVAR(offsetPos, offsetPos - startPos == ordered[i].second, "else str offset is incorrect");
|
DXASSERT_LOCALVAR(offsetPos, offsetPos - startPos == ordered[i].second, "else str offset is incorrect");
|
||||||
IFT(pStream->Write(pName, strlen(pName) + 1, &cbWritten));
|
IFT(pStream->Write(name.data(), name.size() + 1, &cbWritten));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align, and verify we wrote the same number of bytes we though we would.
|
// Align, and verify we wrote the same number of bytes we though we would.
|
||||||
UINT64 bytesWritten = pStream->GetPosition() - startPos;
|
UINT64 bytesWritten = pStream->GetPosition() - startPos;
|
||||||
if (!m_bUnaligned && (bytesWritten % 4 != 0)) {
|
if (!m_bCompat_1_6 && (bytesWritten % 4 != 0)) {
|
||||||
unsigned paddingToAdd = 4 - (bytesWritten % 4);
|
unsigned paddingToAdd = 4 - (bytesWritten % 4);
|
||||||
char padding[4] = {0};
|
char padding[4] = {0};
|
||||||
ULONG cbWritten = 0;
|
ULONG cbWritten = 0;
|
||||||
|
@ -355,24 +379,24 @@ DxilPartWriter *hlsl::NewProgramSignatureWriter(const DxilModule &M, DXIL::Signa
|
||||||
unsigned ValMajor, ValMinor;
|
unsigned ValMajor, ValMinor;
|
||||||
M.GetValidatorVersion(ValMajor, ValMinor);
|
M.GetValidatorVersion(ValMajor, ValMinor);
|
||||||
bool bCompat_1_4 = DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0;
|
bool bCompat_1_4 = DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0;
|
||||||
bool bUnaligned = DXIL::CompareVersions(ValMajor, ValMinor, 1, 7) < 0;
|
bool bCompat_1_6 = DXIL::CompareVersions(ValMajor, ValMinor, 1, 7) < 0;
|
||||||
switch (Kind) {
|
switch (Kind) {
|
||||||
case DXIL::SignatureKind::Input:
|
case DXIL::SignatureKind::Input:
|
||||||
return new DxilProgramSignatureWriter(
|
return new DxilProgramSignatureWriter(
|
||||||
M.GetInputSignature(), domain, true,
|
M.GetInputSignature(), domain, true,
|
||||||
M.GetUseMinPrecision(),
|
M.GetUseMinPrecision(),
|
||||||
bCompat_1_4, bUnaligned);
|
bCompat_1_4, bCompat_1_6);
|
||||||
case DXIL::SignatureKind::Output:
|
case DXIL::SignatureKind::Output:
|
||||||
return new DxilProgramSignatureWriter(
|
return new DxilProgramSignatureWriter(
|
||||||
M.GetOutputSignature(), domain, false,
|
M.GetOutputSignature(), domain, false,
|
||||||
M.GetUseMinPrecision(),
|
M.GetUseMinPrecision(),
|
||||||
bCompat_1_4, bUnaligned);
|
bCompat_1_4, bCompat_1_6);
|
||||||
case DXIL::SignatureKind::PatchConstOrPrim:
|
case DXIL::SignatureKind::PatchConstOrPrim:
|
||||||
return new DxilProgramSignatureWriter(
|
return new DxilProgramSignatureWriter(
|
||||||
M.GetPatchConstOrPrimSignature(), domain,
|
M.GetPatchConstOrPrimSignature(), domain,
|
||||||
/*IsInput*/ M.GetShaderModel()->IsDS(),
|
/*IsInput*/ M.GetShaderModel()->IsDS(),
|
||||||
/*UseMinPrecision*/M.GetUseMinPrecision(),
|
/*UseMinPrecision*/M.GetUseMinPrecision(),
|
||||||
bCompat_1_4, bUnaligned);
|
bCompat_1_4, bCompat_1_6);
|
||||||
case DXIL::SignatureKind::Invalid:
|
case DXIL::SignatureKind::Invalid:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// RUN: %dxilver 1.4 | %dxc -E main -T ps_6_0 -validator-version 1.4 %s | %listparts | FileCheck %s -check-prefix=NODEDUP
|
||||||
|
// RUN: %dxilver 1.7 | %dxc -E main -T ps_6_0 -validator-version 1.7 %s | %listparts | FileCheck %s -check-prefix=DEDUP
|
||||||
|
|
||||||
|
// NODEDUP: #1 - ISG1 (124 bytes)
|
||||||
|
// DEDUP: #1 - ISG1 (116 bytes)
|
||||||
|
|
||||||
|
float4 main(float4 f0 : TEXCOORD0, uint2 u1 : U1, float2 f2 : TEXCOORD2) : SV_Target
|
||||||
|
{
|
||||||
|
return f0 + (u1 * f2).xyxy;
|
||||||
|
}
|
|
@ -107,6 +107,15 @@ FileRunCommandResult FileRunCommandPart::Run(dxc::DxcDllSupport &DllSupport, con
|
||||||
else if (0 == _stricmp(Command.c_str(), "%opt")) {
|
else if (0 == _stricmp(Command.c_str(), "%opt")) {
|
||||||
return RunOpt(DllSupport, Prior);
|
return RunOpt(DllSupport, Prior);
|
||||||
}
|
}
|
||||||
|
else if (0 == _stricmp(Command.c_str(), "%listparts")) {
|
||||||
|
#ifdef _WIN32 // Reflection unsupported
|
||||||
|
return RunListParts(DllSupport, Prior);
|
||||||
|
#else
|
||||||
|
FileRunCommandResult result = FileRunCommandResult::Success("Can't run listparts on non-windows, so just assuming success");
|
||||||
|
result.AbortPipeline = true;
|
||||||
|
return result;
|
||||||
|
#endif // WIN32 - Reflection unsupported
|
||||||
|
}
|
||||||
else if (0 == _stricmp(Command.c_str(), "%D3DReflect")) {
|
else if (0 == _stricmp(Command.c_str(), "%D3DReflect")) {
|
||||||
#ifdef _WIN32 // Reflection unsupported
|
#ifdef _WIN32 // Reflection unsupported
|
||||||
return RunD3DReflect(DllSupport, Prior);
|
return RunD3DReflect(DllSupport, Prior);
|
||||||
|
@ -658,6 +667,71 @@ FileRunCommandResult FileRunCommandPart::RunOpt(dxc::DxcDllSupport &DllSupport,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32 // Reflection unsupported
|
#ifdef _WIN32 // Reflection unsupported
|
||||||
|
FileRunCommandResult FileRunCommandPart::RunListParts(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior) {
|
||||||
|
std::string args(strtrim(Arguments));
|
||||||
|
const char *inputPos = strstr(args.c_str(), "%s");
|
||||||
|
if (inputPos == nullptr && Prior == nullptr) {
|
||||||
|
return FileRunCommandResult::Error("Only supported patterns are input file as argument or prior "
|
||||||
|
"command with disassembly");
|
||||||
|
}
|
||||||
|
|
||||||
|
CComPtr<IDxcLibrary> pLibrary;
|
||||||
|
CComPtr<IDxcBlobEncoding> pSource;
|
||||||
|
CComPtr<IDxcAssembler> pAssembler;
|
||||||
|
CComPtr<IDxcOperationResult> pResult;
|
||||||
|
CComPtr<IDxcContainerReflection> containerReflection;
|
||||||
|
uint32_t partCount;
|
||||||
|
CComPtr<IDxcBlob> pContainerBlob;
|
||||||
|
HRESULT resultStatus;
|
||||||
|
std::ostringstream ss;
|
||||||
|
|
||||||
|
IFT(DllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
|
||||||
|
IFT(DllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
|
||||||
|
|
||||||
|
if (inputPos != nullptr) {
|
||||||
|
args.erase(inputPos - args.c_str(), strlen("%s"));
|
||||||
|
IFT(pLibrary->CreateBlobFromFile(CommandFileName, nullptr, &pSource));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(Prior != nullptr && "else early check should have returned");
|
||||||
|
CComPtr<IDxcAssembler> pAssembler;
|
||||||
|
IFT(DllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
|
||||||
|
IFT(pLibrary->CreateBlobWithEncodingFromPinned(
|
||||||
|
Prior->StdOut.c_str(), Prior->StdOut.size(), CP_UTF8,
|
||||||
|
&pSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
IFT(pAssembler->AssembleToContainer(pSource, &pResult));
|
||||||
|
IFT(pResult->GetStatus(&resultStatus));
|
||||||
|
if (FAILED(resultStatus)) {
|
||||||
|
CComPtr<IDxcBlobEncoding> pAssembleBlob;
|
||||||
|
IFT(pResult->GetErrorBuffer(&pAssembleBlob));
|
||||||
|
return FileRunCommandResult::Error(resultStatus, BlobToUtf8(pAssembleBlob));
|
||||||
|
}
|
||||||
|
IFT(pResult->GetResult(&pContainerBlob));
|
||||||
|
|
||||||
|
IFT(DllSupport.CreateInstance(CLSID_DxcContainerReflection, &containerReflection));
|
||||||
|
IFT(containerReflection->Load(pContainerBlob));
|
||||||
|
IFT(containerReflection->GetPartCount(&partCount));
|
||||||
|
|
||||||
|
ss << "Part count: " << partCount << "\n";
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < partCount; ++i) {
|
||||||
|
uint32_t kind;
|
||||||
|
IFT(containerReflection->GetPartKind(i, &kind));
|
||||||
|
CComPtr<IDxcBlob> pPart;
|
||||||
|
IFT(containerReflection->GetPartContent(i, &pPart));
|
||||||
|
// #0 - SFI0 (8 bytes)
|
||||||
|
ss << "#" << i << " - ";
|
||||||
|
ss << (char)(kind & 0xff) << (char)((kind >> 8) & 0xff) << (char)((kind >> 16) & 0xff) << (char)((kind >> 24) & 0xff);
|
||||||
|
ss << " (" << pPart->GetBufferSize() << " bytes)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ss.flush();
|
||||||
|
|
||||||
|
return FileRunCommandResult::Success(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
FileRunCommandResult FileRunCommandPart::RunD3DReflect(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior) {
|
FileRunCommandResult FileRunCommandPart::RunD3DReflect(dxc::DxcDllSupport &DllSupport, const FileRunCommandResult *Prior) {
|
||||||
std::string args(strtrim(Arguments));
|
std::string args(strtrim(Arguments));
|
||||||
if (args != "%s")
|
if (args != "%s")
|
||||||
|
|
Загрузка…
Ссылка в новой задаче