Skip to content
3 changes: 3 additions & 0 deletions include/dxc/DXIL/DxilModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ class DxilModule {
// Intermediate options that do not make it to DXIL
void SetLegacyResourceReservation(bool legacyResourceReservation);
bool GetLegacyResourceReservation() const;
void SetConsistentBindings(bool consistentBindings);
bool GetConsistentBindings() const;
void ClearIntermediateOptions();

// Hull and Domain shaders.
Expand Down Expand Up @@ -346,6 +348,7 @@ class DxilModule {

enum IntermediateFlags : uint32_t {
LegacyResourceReservation = 1 << 0,
ConsistentBindings = 1 << 1
};

llvm::LLVMContext &m_Ctx;
Expand Down
3 changes: 2 additions & 1 deletion include/dxc/HLSL/HLModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct HLOptions {
bDisableOptimizations(false), PackingStrategy(0),
bUseMinPrecision(false), bDX9CompatMode(false), bFXCCompatMode(false),
bLegacyResourceReservation(false), bForceZeroStoreLifetimes(false),
unused(0) {}
bConsistentBindings(false), unused(0) {}
uint32_t GetHLOptionsRaw() const;
void SetHLOptionsRaw(uint32_t data);
unsigned bDefaultRowMajor : 1;
Expand All @@ -70,6 +70,7 @@ struct HLOptions {
unsigned bLegacyResourceReservation : 1;
unsigned bForceZeroStoreLifetimes : 1;
unsigned bResMayAlias : 1;
unsigned bConsistentBindings : 1;
unsigned unused : 19;
};

Expand Down
1 change: 1 addition & 0 deletions include/dxc/Support/HLSLOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ class DxcOpts {
std::string TimeTrace = ""; // OPT_ftime_trace[EQ]
unsigned TimeTraceGranularity = 500; // OPT_ftime_trace_granularity_EQ
bool VerifyDiagnostics = false; // OPT_verify
bool ConsistentBindings = false; // OPT_consistent_bindings

// Optimization pass enables, disables and selects
OptimizationToggles
Expand Down
3 changes: 3 additions & 0 deletions include/dxc/Support/HLSLOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,9 @@ def getprivate : JoinedOrSeparate<["-", "/"], "getprivate">, Flags<[DriverOption
def nologo : Flag<["-", "/"], "nologo">, Group<hlslcore_Group>, Flags<[DriverOption, HelpHidden]>,
HelpText<"Suppress copyright message">;

def consistent_bindings : Flag<["-", "/"], "consistent-bindings">, Group<hlslcomp_Group>, Flags<[CoreOption]>,
HelpText<"Generate bindings for registers with no pre-declared binding (consistently regardless of optimization).">;

//////////////////////////////////////////////////////////////////////////////
// Rewriter Options

Expand Down
10 changes: 10 additions & 0 deletions lib/DXIL/DxilModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,16 @@ bool DxilModule::GetLegacyResourceReservation() const {
return (m_IntermediateFlags & LegacyResourceReservation) != 0;
}

void DxilModule::SetConsistentBindings(bool consistentBindings) {
m_IntermediateFlags &= ~ConsistentBindings;
if (consistentBindings)
m_IntermediateFlags |= ConsistentBindings;
}

bool DxilModule::GetConsistentBindings() const {
return (m_IntermediateFlags & ConsistentBindings) != 0;
}

void DxilModule::ClearIntermediateOptions() { m_IntermediateFlags = 0; }

unsigned DxilModule::GetInputControlPointCount() const {
Expand Down
4 changes: 4 additions & 0 deletions lib/DxcSupport/HLSLOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,10 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
opts.TimeReport = Args.hasFlag(OPT_ftime_report, OPT_INVALID, false);
opts.TimeTrace = Args.hasFlag(OPT_ftime_trace, OPT_INVALID, false) ? "-" : "";
opts.VerifyDiagnostics = Args.hasFlag(OPT_verify, OPT_INVALID, false);

opts.ConsistentBindings =
Args.hasFlag(OPT_consistent_bindings, OPT_INVALID, false);

if (Args.hasArg(OPT_ftime_trace_EQ))
opts.TimeTrace = Args.getLastArgValue(OPT_ftime_trace_EQ);
if (Arg *A = Args.getLastArg(OPT_ftime_trace_granularity_EQ)) {
Expand Down
6 changes: 5 additions & 1 deletion lib/HLSL/DxilCondenseResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,8 @@ class DxilLowerCreateHandleForLib : public ModulePass {
ResourceRegisterAllocator.GatherReservedRegisters(DM);

// Remove unused resources.
DM.RemoveResourcesWithUnusedSymbols();
if (!DM.GetConsistentBindings())
DM.RemoveResourcesWithUnusedSymbols();

unsigned newResources = DM.GetCBuffers().size() + DM.GetUAVs().size() +
DM.GetSRVs().size() + DM.GetSamplers().size();
Expand All @@ -571,6 +572,9 @@ class DxilLowerCreateHandleForLib : public ModulePass {

bChanged |= ResourceRegisterAllocator.AllocateRegisters(DM);

if (DM.GetConsistentBindings())
DM.RemoveResourcesWithUnusedSymbols();

// Fill in top-level CBuffer variable usage bit
UpdateCBufferUsage();

Expand Down
1 change: 1 addition & 0 deletions lib/HLSL/DxilGenerationPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) {
// bool m_bDisableOptimizations;
M.SetDisableOptimization(H.GetHLOptions().bDisableOptimizations);
M.SetLegacyResourceReservation(H.GetHLOptions().bLegacyResourceReservation);
M.SetConsistentBindings(H.GetHLOptions().bConsistentBindings);
// bool m_bDisableMathRefactoring;
// bool m_bEnableDoublePrecision;
// bool m_bEnableDoubleExtensions;
Expand Down
20 changes: 14 additions & 6 deletions lib/HLSL/HLModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,19 @@ void HLModule::RemoveFunction(llvm::Function *F) {
namespace {
template <typename TResource>
bool RemoveResource(std::vector<std::unique_ptr<TResource>> &vec,
GlobalVariable *pVariable, bool keepAllocated) {
GlobalVariable *pVariable, bool keepAllocated,
bool consistentBindings) {
for (auto p = vec.begin(), e = vec.end(); p != e; ++p) {
if ((*p)->GetGlobalSymbol() != pVariable)
continue;

if (keepAllocated && (*p)->IsAllocated()) {
if ((keepAllocated && (*p)->IsAllocated()) || consistentBindings) {
// Keep the resource, but it has no more symbol.
(*p)->SetGlobalSymbol(UndefValue::get(pVariable->getType()));
} else {
// Erase the resource alltogether and update IDs of subsequent ones
p = vec.erase(p);

for (e = vec.end(); p != e; ++p) {
unsigned ID = (*p)->GetID() - 1;
(*p)->SetID(ID);
Expand All @@ -262,16 +264,22 @@ void HLModule::RemoveGlobal(llvm::GlobalVariable *GV) {
// register range from being allocated to other resources.
bool keepAllocated = GetHLOptions().bLegacyResourceReservation;

// Consistent bindings are different than -flegacy-resource-reservation;
// We need the IDs to stay the same, but it's fine to remove unused registers.
// It's actually wanted, because that allows us to know what registers are
// optimized out.
bool consistentBindings = GetHLOptions().bConsistentBindings;

// This could be considerably faster - check variable type to see which
// resource type this is rather than scanning all lists, and look for
// usage and removal patterns.
if (RemoveResource(m_CBuffers, GV, keepAllocated))
if (RemoveResource(m_CBuffers, GV, keepAllocated, consistentBindings))
return;
if (RemoveResource(m_SRVs, GV, keepAllocated))
if (RemoveResource(m_SRVs, GV, keepAllocated, consistentBindings))
return;
if (RemoveResource(m_UAVs, GV, keepAllocated))
if (RemoveResource(m_UAVs, GV, keepAllocated, consistentBindings))
return;
if (RemoveResource(m_Samplers, GV, keepAllocated))
if (RemoveResource(m_Samplers, GV, keepAllocated, consistentBindings))
return;
// TODO: do m_TGSMVariables and m_StreamOutputs need maintenance?
}
Expand Down
2 changes: 2 additions & 0 deletions tools/clang/include/clang/Frontend/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ class CodeGenOptions : public CodeGenOptionsBase {
bool HLSLOnlyWarnOnUnrollFail = false;
/// Whether use legacy resource reservation.
bool HLSLLegacyResourceReservation = false;
/// Whether to keep bindings consistent even if optimized out.
bool HLSLConsistentBindings = false;
/// Set [branch] on every if.
bool HLSLPreferControlFlow = false;
/// Set [flatten] on every if.
Expand Down
1 change: 1 addition & 0 deletions tools/clang/lib/CodeGen/CGHLSLMS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM)
opts.PackingStrategy = CGM.getCodeGenOpts().HLSLSignaturePackingStrategy;
opts.bLegacyResourceReservation =
CGM.getCodeGenOpts().HLSLLegacyResourceReservation;
opts.bConsistentBindings = CGM.getCodeGenOpts().HLSLConsistentBindings;
opts.bForceZeroStoreLifetimes =
CGM.getCodeGenOpts().HLSLForceZeroStoreLifetimes;

Expand Down
1 change: 1 addition & 0 deletions tools/clang/tools/dxcompiler/dxcompilerobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,7 @@ class DxcCompiler : public IDxcCompiler3,
compiler.getCodeGenOpts().HLSLAvoidControlFlow = Opts.AvoidFlowControl;
compiler.getCodeGenOpts().HLSLLegacyResourceReservation =
Opts.LegacyResourceReservation;
compiler.getCodeGenOpts().HLSLConsistentBindings = Opts.ConsistentBindings;
compiler.getCodeGenOpts().HLSLDefines = defines;
compiler.getCodeGenOpts().HLSLPreciseOutputs = Opts.PreciseOutputs;
compiler.getCodeGenOpts().MainFileName = pMainFile;
Expand Down