diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 4fdb82f2ca..8f7cb7685f 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -23,6 +23,7 @@ The included licenses apply to the following files: - Fixed regression: [#7508](https://github.com/microsoft/DirectXShaderCompiler/issues/7508) crash when calling `Load` with `status`. - Header file `dxcpix.h` was added to the release package. - Moved Linear Algebra (Cooperative Vector) DXIL Opcodes to experimental Shader Model 6.10 +- Added `-fhlsl-unused-resource-bindings=` an option to allow deciding on how to treat unused resource bindings in DXIL; `strip` (default) or `reserve-all`. `strip` will strip unused resources before generating bindings for resources without a `: register`, and `reserve-all` will keep them reserved for generated bindings while stripping them afterwards. See [explanation](https://github.com/microsoft/DirectXShaderCompiler/pull/7643#issuecomment-3496917202) for more details. ### Version 1.8.2505 diff --git a/include/dxc/DXIL/DxilConstants.h b/include/dxc/DXIL/DxilConstants.h index d66f14a1e9..b6b18a67b8 100644 --- a/include/dxc/DXIL/DxilConstants.h +++ b/include/dxc/DXIL/DxilConstants.h @@ -15,6 +15,12 @@ namespace hlsl { +enum class UnusedResourceBinding : uint32_t { Strip, ReserveAll, Count }; + +static_assert(UnusedResourceBinding::Count <= UnusedResourceBinding(7), + "Only 3 bits are reserved for UnusedResourceBinding by HLOptions " + "and ShaderFlags"); + /* import hctdb_instrhelp */ diff --git a/include/dxc/DXIL/DxilModule.h b/include/dxc/DXIL/DxilModule.h index 3f1ba12f86..0b6aff27d7 100644 --- a/include/dxc/DXIL/DxilModule.h +++ b/include/dxc/DXIL/DxilModule.h @@ -112,7 +112,7 @@ class DxilModule { const std::vector> &GetUAVs() const; void RemoveUnusedResources(); - void RemoveResourcesWithUnusedSymbols(); + bool RemoveResourcesWithUnusedSymbols(); void RemoveFunction(llvm::Function *F); bool RenameResourcesWithPrefix(const std::string &prefix); @@ -287,6 +287,9 @@ class DxilModule { // Intermediate options that do not make it to DXIL void SetLegacyResourceReservation(bool legacyResourceReservation); bool GetLegacyResourceReservation() const; + + void SetUnusedResourceBinding(UnusedResourceBinding unusedResourceBinding); + UnusedResourceBinding GetUnusedResourceBinding() const; void ClearIntermediateOptions(); // Hull and Domain shaders. @@ -344,9 +347,7 @@ class DxilModule { DXIL::PrimitiveTopology::Undefined; unsigned m_ActiveStreamMask = 0; - enum IntermediateFlags : uint32_t { - LegacyResourceReservation = 1 << 0, - }; + enum IntermediateFlags : uint32_t { LegacyResourceReservation = 1 << 0 }; llvm::LLVMContext &m_Ctx; llvm::Module *m_pModule = nullptr; @@ -383,6 +384,7 @@ class DxilModule { bool m_bUseMinPrecision = true; // use min precision by default; bool m_bAllResourcesBound = false; bool m_bResMayAlias = false; + UnusedResourceBinding m_unusedResourceBinding = UnusedResourceBinding::Strip; // properties from HLModule that should not make it to the final DXIL uint32_t m_IntermediateFlags = 0; diff --git a/include/dxc/DXIL/DxilShaderFlags.h b/include/dxc/DXIL/DxilShaderFlags.h index 7b065c63fa..44c1ddfdfb 100644 --- a/include/dxc/DXIL/DxilShaderFlags.h +++ b/include/dxc/DXIL/DxilShaderFlags.h @@ -16,6 +16,7 @@ namespace hlsl { class DxilModule; struct DxilFunctionProps; +enum class UnusedResourceBinding : uint32_t; } namespace llvm { @@ -219,6 +220,14 @@ class ShaderFlags { void SetRequiresGroup(bool flag) { m_bRequiresGroup = flag; } bool GetRequiresGroup() const { return m_bRequiresGroup; } + void SetUnusedResourceBinding(UnusedResourceBinding bindings) { + m_UnusedResourceBinding = unsigned(bindings); + } + + UnusedResourceBinding GetUnusedResourceBinding() { + return UnusedResourceBinding(m_UnusedResourceBinding); + } + private: // Bit: 0 unsigned @@ -359,7 +368,9 @@ class ShaderFlags { unsigned m_bRequiresGroup : 1; // SHADER_FEATURE_OPT_REQUIRES_GROUP // (OptFeatureInfo_RequiresGroup) - uint32_t m_align1 : 23; // align to 64 bit. + unsigned m_UnusedResourceBinding : 3; + + uint32_t m_align1 : 20; // align to 64 bit. }; } // namespace hlsl diff --git a/include/dxc/HLSL/HLModule.h b/include/dxc/HLSL/HLModule.h index 653fc967d5..de851121fb 100644 --- a/include/dxc/HLSL/HLModule.h +++ b/include/dxc/HLSL/HLModule.h @@ -54,7 +54,7 @@ struct HLOptions { bDisableOptimizations(false), PackingStrategy(0), bUseMinPrecision(false), bDX9CompatMode(false), bFXCCompatMode(false), bLegacyResourceReservation(false), bForceZeroStoreLifetimes(false), - unused(0) {} + bUnusedResourceBinding(0), unused(0) {} uint32_t GetHLOptionsRaw() const; void SetHLOptionsRaw(uint32_t data); unsigned bDefaultRowMajor : 1; @@ -70,7 +70,8 @@ struct HLOptions { unsigned bLegacyResourceReservation : 1; unsigned bForceZeroStoreLifetimes : 1; unsigned bResMayAlias : 1; - unsigned unused : 19; + unsigned bUnusedResourceBinding : 3; + unsigned unused : 17; }; typedef std::unordered_map, Flags<[DriverOption def nologo : Flag<["-", "/"], "nologo">, Group, Flags<[DriverOption, HelpHidden]>, HelpText<"Suppress copyright message">; +def fhlsl_unused_resource_bindings_EQ : Joined<["-"], "fhlsl-unused-resource-bindings=">, Group, Flags<[CoreOption]>, + HelpText<"Control handling of unused resource bindings:\n\t\t\t'strip' (default, unused resources are stripped and their binding slots are freed up).\n\t\t\t'reserve-all' (do not use binding slots of unused resources when assigning bindings).">; + ////////////////////////////////////////////////////////////////////////////// // Rewriter Options diff --git a/lib/DXIL/DxilModule.cpp b/lib/DXIL/DxilModule.cpp index f4abdd15aa..162732fd89 100644 --- a/lib/DXIL/DxilModule.cpp +++ b/lib/DXIL/DxilModule.cpp @@ -586,6 +586,15 @@ bool DxilModule::GetLegacyResourceReservation() const { return (m_IntermediateFlags & LegacyResourceReservation) != 0; } +void DxilModule::SetUnusedResourceBinding( + UnusedResourceBinding unusedResourceBinding) { + m_unusedResourceBinding = unusedResourceBinding; +} + +UnusedResourceBinding DxilModule::GetUnusedResourceBinding() const { + return m_unusedResourceBinding; +} + void DxilModule::ClearIntermediateOptions() { m_IntermediateFlags = 0; } unsigned DxilModule::GetInputControlPointCount() const { @@ -1021,8 +1030,9 @@ void DxilModule::RemoveUnusedResources() { namespace { template -static void RemoveResourcesWithUnusedSymbolsHelper( +static bool RemoveResourcesWithUnusedSymbolsHelper( std::vector> &vec) { + bool modif = false; unsigned resID = 0; std::unordered_set eraseList; // Need in case of duplicate defs of lib resources @@ -1034,6 +1044,7 @@ static void RemoveResourcesWithUnusedSymbolsHelper( p = vec.erase(c); if (GlobalVariable *GV = dyn_cast(symbol)) eraseList.insert(GV); + modif = true; continue; } if ((*c)->GetID() != resID) { @@ -1044,14 +1055,17 @@ static void RemoveResourcesWithUnusedSymbolsHelper( for (auto gv : eraseList) { gv->eraseFromParent(); } + return modif; } } // namespace -void DxilModule::RemoveResourcesWithUnusedSymbols() { - RemoveResourcesWithUnusedSymbolsHelper(m_SRVs); - RemoveResourcesWithUnusedSymbolsHelper(m_UAVs); - RemoveResourcesWithUnusedSymbolsHelper(m_CBuffers); - RemoveResourcesWithUnusedSymbolsHelper(m_Samplers); +bool DxilModule::RemoveResourcesWithUnusedSymbols() { + bool modif = false; + modif |= RemoveResourcesWithUnusedSymbolsHelper(m_SRVs); + modif |= RemoveResourcesWithUnusedSymbolsHelper(m_UAVs); + modif |= RemoveResourcesWithUnusedSymbolsHelper(m_CBuffers); + modif |= RemoveResourcesWithUnusedSymbolsHelper(m_Samplers); + return modif; } namespace { @@ -1533,6 +1547,7 @@ void DxilModule::LoadDxilMetadata() { m_bUseMinPrecision = !m_ShaderFlags.GetUseNativeLowPrecision(); m_bDisableOptimizations = m_ShaderFlags.GetDisableOptimizations(); m_bAllResourcesBound = m_ShaderFlags.GetAllResourcesBound(); + m_unusedResourceBinding = m_ShaderFlags.GetUnusedResourceBinding(); m_bResMayAlias = !m_ShaderFlags.GetResMayNotAlias(); } diff --git a/lib/DXIL/DxilShaderFlags.cpp b/lib/DXIL/DxilShaderFlags.cpp index 993038aaf1..9fc096dc86 100644 --- a/lib/DXIL/DxilShaderFlags.cpp +++ b/lib/DXIL/DxilShaderFlags.cpp @@ -47,7 +47,7 @@ ShaderFlags::ShaderFlags() m_bAdvancedTextureOps(false), m_bWriteableMSAATextures(false), m_bReserved(false), m_bSampleCmpGradientOrBias(false), m_bExtendedCommandInfo(false), m_bUsesDerivatives(false), - m_bRequiresGroup(false), m_align1(0) { + m_bRequiresGroup(false), m_UnusedResourceBinding(0), m_align1(0) { // Silence unused field warnings (void)m_align1; } @@ -412,6 +412,7 @@ ShaderFlags ShaderFlags::CollectShaderFlags(const Function *F, flag.SetUseNativeLowPrecision(!M->GetUseMinPrecision()); flag.SetDisableOptimizations(M->GetDisableOptimization()); flag.SetAllResourcesBound(M->GetAllResourcesBound()); + flag.SetUnusedResourceBinding(M->GetUnusedResourceBinding()); bool hasDouble = false; // ddiv dfma drcp d2i d2u i2d u2d. diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 0c9330b1d1..f46f70105d 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -865,6 +865,21 @@ 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); + + std::string UnusedResources = + Args.getLastArgValue(OPT_fhlsl_unused_resource_bindings_EQ, "strip"); + + if (UnusedResources == "strip") + opts.UnusedResourceBinding = UnusedResourceBinding::Strip; + else if (UnusedResources == "reserve-all") + opts.UnusedResourceBinding = UnusedResourceBinding::ReserveAll; + else { + errors << "Error: Invalid value for -fhlsl-unused-resource-bindings option " + "specified (" + << UnusedResources << "). Must be one of: strip, reserve-all"; + return 1; + } + opts.Verbose = Args.hasFlag(OPT_verbose, OPT_INVALID, false); if (Args.hasArg(OPT_ftime_trace_EQ)) opts.TimeTrace = Args.getLastArgValue(OPT_ftime_trace_EQ); diff --git a/lib/HLSL/DxilCondenseResources.cpp b/lib/HLSL/DxilCondenseResources.cpp index 09dd9cea64..0efee67614 100644 --- a/lib/HLSL/DxilCondenseResources.cpp +++ b/lib/HLSL/DxilCondenseResources.cpp @@ -550,11 +550,11 @@ class DxilLowerCreateHandleForLib : public ModulePass { ResourceRegisterAllocator.GatherReservedRegisters(DM); // Remove unused resources. - DM.RemoveResourcesWithUnusedSymbols(); + if (DM.GetUnusedResourceBinding() == UnusedResourceBinding::Strip) + bChanged |= DM.RemoveResourcesWithUnusedSymbols(); unsigned newResources = DM.GetCBuffers().size() + DM.GetUAVs().size() + DM.GetSRVs().size() + DM.GetSamplers().size(); - bChanged = bChanged || (numResources != newResources); if (0 == newResources) return bChanged; @@ -562,15 +562,19 @@ class DxilLowerCreateHandleForLib : public ModulePass { { DxilValueCache *DVC = &getAnalysis(); bool bLocalChanged = LegalizeResources(M, DVC); - if (bLocalChanged) { + if (bLocalChanged && + DM.GetUnusedResourceBinding() == UnusedResourceBinding::Strip) { // Remove unused resources. - DM.RemoveResourcesWithUnusedSymbols(); + bChanged |= DM.RemoveResourcesWithUnusedSymbols(); } bChanged |= bLocalChanged; } bChanged |= ResourceRegisterAllocator.AllocateRegisters(DM); + if (DM.GetUnusedResourceBinding() == UnusedResourceBinding::ReserveAll) + bChanged |= DM.RemoveResourcesWithUnusedSymbols(); + // Fill in top-level CBuffer variable usage bit UpdateCBufferUsage(); diff --git a/lib/HLSL/DxilGenerationPass.cpp b/lib/HLSL/DxilGenerationPass.cpp index c3a6ad7dfc..d08041c77b 100644 --- a/lib/HLSL/DxilGenerationPass.cpp +++ b/lib/HLSL/DxilGenerationPass.cpp @@ -155,6 +155,8 @@ void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) { // bool m_bDisableOptimizations; M.SetDisableOptimization(H.GetHLOptions().bDisableOptimizations); M.SetLegacyResourceReservation(H.GetHLOptions().bLegacyResourceReservation); + M.SetUnusedResourceBinding( + UnusedResourceBinding(H.GetHLOptions().bUnusedResourceBinding)); // bool m_bDisableMathRefactoring; // bool m_bEnableDoublePrecision; // bool m_bEnableDoubleExtensions; diff --git a/lib/HLSL/HLModule.cpp b/lib/HLSL/HLModule.cpp index bab6e23a30..af55bf616e 100644 --- a/lib/HLSL/HLModule.cpp +++ b/lib/HLSL/HLModule.cpp @@ -231,17 +231,20 @@ void HLModule::RemoveFunction(llvm::Function *F) { namespace { template bool RemoveResource(std::vector> &vec, - GlobalVariable *pVariable, bool keepAllocated) { + GlobalVariable *pVariable, bool keepAllocated, + UnusedResourceBinding unusedResourceBinding) { for (auto p = vec.begin(), e = vec.end(); p != e; ++p) { if ((*p)->GetGlobalSymbol() != pVariable) continue; - if (keepAllocated && (*p)->IsAllocated()) { + if ((keepAllocated && (*p)->IsAllocated()) || + unusedResourceBinding == UnusedResourceBinding::ReserveAll) { // 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); @@ -262,16 +265,19 @@ void HLModule::RemoveGlobal(llvm::GlobalVariable *GV) { // register range from being allocated to other resources. bool keepAllocated = GetHLOptions().bLegacyResourceReservation; + UnusedResourceBinding unusedResourceBinding = + UnusedResourceBinding(GetHLOptions().bUnusedResourceBinding); + // 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, unusedResourceBinding)) return; - if (RemoveResource(m_SRVs, GV, keepAllocated)) + if (RemoveResource(m_SRVs, GV, keepAllocated, unusedResourceBinding)) return; - if (RemoveResource(m_UAVs, GV, keepAllocated)) + if (RemoveResource(m_UAVs, GV, keepAllocated, unusedResourceBinding)) return; - if (RemoveResource(m_Samplers, GV, keepAllocated)) + if (RemoveResource(m_Samplers, GV, keepAllocated, unusedResourceBinding)) return; // TODO: do m_TGSMVariables and m_StreamOutputs need maintenance? } diff --git a/tools/clang/include/clang/Frontend/CodeGenOptions.h b/tools/clang/include/clang/Frontend/CodeGenOptions.h index 859cba53da..b69cf75360 100644 --- a/tools/clang/include/clang/Frontend/CodeGenOptions.h +++ b/tools/clang/include/clang/Frontend/CodeGenOptions.h @@ -187,6 +187,9 @@ class CodeGenOptions : public CodeGenOptionsBase { bool HLSLOnlyWarnOnUnrollFail = false; /// Whether use legacy resource reservation. bool HLSLLegacyResourceReservation = false; + /// How to handle unused resource bindings. + hlsl::UnusedResourceBinding HLSLUnusedResourceBinding = + hlsl::UnusedResourceBinding::Strip; /// Set [branch] on every if. bool HLSLPreferControlFlow = false; /// Set [flatten] on every if. diff --git a/tools/clang/lib/CodeGen/CGHLSLMS.cpp b/tools/clang/lib/CodeGen/CGHLSLMS.cpp index 6c68381a20..c4edd003de 100644 --- a/tools/clang/lib/CodeGen/CGHLSLMS.cpp +++ b/tools/clang/lib/CodeGen/CGHLSLMS.cpp @@ -400,6 +400,8 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM) opts.PackingStrategy = CGM.getCodeGenOpts().HLSLSignaturePackingStrategy; opts.bLegacyResourceReservation = CGM.getCodeGenOpts().HLSLLegacyResourceReservation; + opts.bUnusedResourceBinding = + unsigned(CGM.getCodeGenOpts().HLSLUnusedResourceBinding); opts.bForceZeroStoreLifetimes = CGM.getCodeGenOpts().HLSLForceZeroStoreLifetimes; diff --git a/tools/clang/test/HLSLFileCheck/d3dreflect/consistent_bindings_complex.hlsl b/tools/clang/test/HLSLFileCheck/d3dreflect/consistent_bindings_complex.hlsl new file mode 100644 index 0000000000..2aef348bd9 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/d3dreflect/consistent_bindings_complex.hlsl @@ -0,0 +1,190 @@ +// RUN: %dxc -T lib_6_3 -auto-binding-space 0 -fhlsl-unused-resource-bindings=reserve-all %s | %D3DReflect %s | FileCheck %s + +RWByteAddressBuffer output1; +RWByteAddressBuffer output2; +RWByteAddressBuffer output3 : register(u0); +RWByteAddressBuffer output4 : register(space1); +RWByteAddressBuffer output5 : SEMA; +RWByteAddressBuffer output6; +RWByteAddressBuffer output7 : register(u1); +RWByteAddressBuffer output8[12] : register(u3); +RWByteAddressBuffer output9[12]; +RWByteAddressBuffer output10[33] : register(space1); +RWByteAddressBuffer output11[33] : register(space2); +RWByteAddressBuffer output12[33] : register(u0, space2); + +StructuredBuffer test5; +ByteAddressBuffer input13 : SEMA; +ByteAddressBuffer input14; +ByteAddressBuffer input15 : register(t0); +ByteAddressBuffer input16[12] : register(t3); +ByteAddressBuffer input17[2] : register(space1); +ByteAddressBuffer input18[12] : register(t1, space1); +ByteAddressBuffer input19[3] : register(space1); +ByteAddressBuffer input20 : register(space1); +Texture2D tex; + +SamplerState sampler0; +SamplerState sampler1; +SamplerState sampler2 : register(s0); +SamplerState sampler3 : register(space1); +SamplerState sampler4 : register(s0, space1); + +cbuffer test : register(b0) { float a; }; +cbuffer test2 { float b; }; +cbuffer test3 : register(space1) { float c; }; +cbuffer test4 : register(space1) { float d; }; + +float e; //$Global is always the first to receive bindings before cbuffers without register annotation + +[shader("compute")] +[numthreads(16, 16, 1)] +void main(uint id : SV_DispatchThreadID) { + output1.Store(0, test5[0]); + output2.Store(id * 4, a * b * c * d * e); //Only use 1 output, but this won't result into output2 receiving wrong bindings + output3.Store(0, input13.Load(0)); + output4.Store(0, input14.Load(0)); + output5.Store(0, input15.Load(0)); + output6.Store(0, input16[0].Load(0)); + output7.Store(0, input17[0].Load(0)); + output8[0].Store(0, input18[0].Load(0)); + output9[0].Store(0, input19[0].Load(0)); + output10[0].Store(0, input20.Load(0)); + output11[0].Store(0, tex.SampleLevel(sampler0, 0.xx, 0)); + output12[0].Store(0, tex.SampleLevel(sampler1, 0.xx, 0) * tex.SampleLevel(sampler2, 0.xx, 0) * tex.SampleLevel(sampler3, 0.xx, 0) * tex.SampleLevel(sampler4, 0.xx, 0)); +} + +// CHECK: ID3D12LibraryReflection: +// CHECK: D3D12_LIBRARY_DESC: +// CHECK: FunctionCount: 1 +// CHECK: ID3D12FunctionReflection: +// CHECK: D3D12_FUNCTION_DESC: Name: main +// CHECK: Shader Version: Compute 6.3 +// CHECK: BoundResources: 32 +// CHECK: Bound Resources: +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: $Globals +// CHECK: Type: D3D_SIT_CBUFFER +// CHECK: BindPoint: 1 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: test +// CHECK: Type: D3D_SIT_CBUFFER +// CHECK: BindPoint: 0 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: test2 +// CHECK: Type: D3D_SIT_CBUFFER +// CHECK: BindPoint: 2 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: test3 +// CHECK: Type: D3D_SIT_CBUFFER +// CHECK: BindPoint: 0 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: test4 +// CHECK: Type: D3D_SIT_CBUFFER +// CHECK: BindPoint: 1 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: sampler0 +// CHECK: Type: D3D_SIT_SAMPLER +// CHECK: BindPoint: 1 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: sampler1 +// CHECK: Type: D3D_SIT_SAMPLER +// CHECK: BindPoint: 2 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: sampler2 +// CHECK: Type: D3D_SIT_SAMPLER +// CHECK: BindPoint: 0 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: sampler3 +// CHECK: Type: D3D_SIT_SAMPLER +// CHECK: BindPoint: 1 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: sampler4 +// CHECK: Type: D3D_SIT_SAMPLER +// CHECK: BindPoint: 0 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: test5 +// CHECK: Type: D3D_SIT_STRUCTURED +// CHECK: BindPoint: 1 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: input13 +// CHECK: Type: D3D_SIT_BYTEADDRESS +// CHECK: BindPoint: 2 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: input14 +// CHECK: Type: D3D_SIT_BYTEADDRESS +// CHECK: BindPoint: 15 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: input15 +// CHECK: Type: D3D_SIT_BYTEADDRESS +// CHECK: BindPoint: 0 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: input16 +// CHECK: Type: D3D_SIT_BYTEADDRESS +// CHECK: BindPoint: 3 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: input17 +// CHECK: Type: D3D_SIT_BYTEADDRESS +// CHECK: BindPoint: 13 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: input18 +// CHECK: Type: D3D_SIT_BYTEADDRESS +// CHECK: BindPoint: 1 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: input19 +// CHECK: Type: D3D_SIT_BYTEADDRESS +// CHECK: BindPoint: 15 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: input20 +// CHECK: Type: D3D_SIT_BYTEADDRESS +// CHECK: BindPoint: 0 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: tex +// CHECK: BindPoint: 16 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output1 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 2 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output2 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 15 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output3 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 0 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output4 +// CHECK: BindPoint: 0 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output5 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 16 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output6 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 17 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output7 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 1 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output8 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 3 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output9 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 18 +// CHECK: Space: 0 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output10 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 1 +// CHECK: Space: 1 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output11 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 33 +// CHECK: Space: 2 +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: output12 +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 0 +// CHECK: Space: 2 \ No newline at end of file diff --git a/tools/clang/test/HLSLFileCheck/d3dreflect/consistent_bindings_simple.hlsl b/tools/clang/test/HLSLFileCheck/d3dreflect/consistent_bindings_simple.hlsl new file mode 100644 index 0000000000..021eb82877 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/d3dreflect/consistent_bindings_simple.hlsl @@ -0,0 +1,58 @@ +// RUN: %dxc -T lib_6_3 -auto-binding-space 0 -fhlsl-unused-resource-bindings=reserve-all %s | %D3DReflect %s | FileCheck %s -check-prefix=CHECK +// RUN: %dxc -T cs_6_3 -E mainA -auto-binding-space 0 -fhlsl-unused-resource-bindings=reserve-all %s | %D3DReflect %s | FileCheck %s -check-prefix=CHECK2 +// RUN: %dxc -T cs_6_3 -E mainB -auto-binding-space 0 -fhlsl-unused-resource-bindings=reserve-all %s | %D3DReflect %s | FileCheck %s -check-prefix=CHECK3 + +RWByteAddressBuffer a; +RWByteAddressBuffer b; + +[shader("compute")] +[numthreads(16, 16, 1)] +void mainA(uint id : SV_DispatchThreadID) { + a.Store(0, float4(id, 0.xxx)); +} + +[shader("compute")] +[numthreads(16, 16, 1)] +void mainB(uint id : SV_DispatchThreadID) { + b.Store(0, float4(id, 0.xxx)); +} + +// CHECK: ID3D12LibraryReflection: +// CHECK: D3D12_LIBRARY_DESC: +// CHECK: FunctionCount: 2 +// CHECK: ID3D12FunctionReflection: +// CHECK: D3D12_FUNCTION_DESC: Name: mainA +// CHECK: Shader Version: Compute 6.3 +// CHECK: BoundResources: 1 +// CHECK: Bound Resources: +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: a +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 0 +// CHECK: Space: 0 +// CHECK: ID3D12FunctionReflection: +// CHECK: D3D12_FUNCTION_DESC: Name: mainB +// CHECK: Shader Version: Compute 6.3 +// CHECK: BoundResources: 1 +// CHECK: Bound Resources: +// CHECK: D3D12_SHADER_INPUT_BIND_DESC: Name: b +// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK: BindPoint: 1 +// CHECK: Space: 0 + +// CHECK2: ID3D12ShaderReflection: +// CHECK2: D3D12_SHADER_DESC: +// CHECK2: Shader Version: Compute +// CHECK2: Bound Resources: +// CHECK2: D3D12_SHADER_INPUT_BIND_DESC: Name: a +// CHECK2: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK2: BindPoint: 0 +// CHECK2: Space: 0 + +// CHECK3: ID3D12ShaderReflection: +// CHECK3: D3D12_SHADER_DESC: +// CHECK3: Shader Version: Compute +// CHECK3: Bound Resources: +// CHECK3: D3D12_SHADER_INPUT_BIND_DESC: Name: b +// CHECK3: Type: D3D_SIT_UAV_RWBYTEADDRESS +// CHECK3: BindPoint: 1 +// CHECK3: Space: 0 \ No newline at end of file diff --git a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp index 230047b4a8..f96cc7e6d3 100644 --- a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp +++ b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp @@ -1595,6 +1595,8 @@ class DxcCompiler : public IDxcCompiler3, compiler.getCodeGenOpts().HLSLAvoidControlFlow = Opts.AvoidFlowControl; compiler.getCodeGenOpts().HLSLLegacyResourceReservation = Opts.LegacyResourceReservation; + compiler.getCodeGenOpts().HLSLUnusedResourceBinding = + Opts.UnusedResourceBinding; compiler.getCodeGenOpts().HLSLDefines = defines; compiler.getCodeGenOpts().HLSLPreciseOutputs = Opts.PreciseOutputs; compiler.getCodeGenOpts().MainFileName = pMainFile;