From 15d1c6c51c5f24663d2567d7e56da62a2bca1c22 Mon Sep 17 00:00:00 2001 From: Yong He Date: Mon, 30 Sep 2024 12:50:30 -0700 Subject: [PATCH] Add COM API for querying metadata. (#5168) * Add COM API for querying metadata. * Fix tests. * fix test. --- include/slang.h | 27 ++++++ .../slang-artifact-associated-impl.cpp | 20 ++++ .../slang-artifact-associated-impl.h | 8 ++ .../compiler-core/slang-artifact-associated.h | 2 +- .../record/slang-component-type.cpp | 19 ++++ .../record/slang-component-type.h | 9 ++ .../record/slang-entrypoint.h | 17 ++++ .../slang-record-replay/record/slang-module.h | 17 ++++ .../record/slang-type-conformance.h | 17 ++++ source/slang/slang-compiler.h | 65 +++++++++++++ source/slang/slang-parameter-binding.cpp | 11 ++- source/slang/slang.cpp | 97 +++++++++++++++---- .../hlsl-to-vulkan-combined.hlsl.expected | 4 +- .../hlsl-to-vulkan-global.hlsl.expected | 4 +- .../dynamic-resource-gl.slang.1.expected | 10 +- .../unit-test-image-format-reflection.cpp | 2 +- .../unit-test-parameter-usage-reflection.cpp | 68 +++++++++++++ 17 files changed, 360 insertions(+), 37 deletions(-) create mode 100644 tools/slang-unit-test/unit-test-parameter-usage-reflection.cpp diff --git a/include/slang.h b/include/slang.h index 8e42632ff9..81b3ac1cbe 100644 --- a/include/slang.h +++ b/include/slang.h @@ -5280,6 +5280,22 @@ namespace slang #define SLANG_UUID_ISession ISession::getTypeGuid() + struct IMetadata : public ISlangCastable + { + SLANG_COM_INTERFACE(0x8044a8a3, 0xddc0, 0x4b7f, { 0xaf, 0x8e, 0x2, 0x6e, 0x90, 0x5d, 0x73, 0x32 }) + + /* + Returns whether a resource parameter at the specifieid binding location is actually being used + in the compiled shader. + */ + virtual SlangResult isParameterLocationUsed( + SlangParameterCategory category, // is this a `t` register? `s` register? + SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan + SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan + bool& outUsed) = 0; + }; + #define SLANG_UUID_IMetadata IMetadata::getTypeGuid() + /** A component type is a unit of shader code layout, reflection, and linking. A component type is a unit of shader code that can be included into @@ -5492,6 +5508,17 @@ namespace slang SlangInt targetIndex, IBlob** outCode, IBlob** outDiagnostics = nullptr) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + IMetadata** outMetadata, + IBlob** outDiagnostics = nullptr) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + IMetadata** outMetadata, + IBlob** outDiagnostics = nullptr) = 0; }; #define SLANG_UUID_IComponentType IComponentType::getTypeGuid() diff --git a/source/compiler-core/slang-artifact-associated-impl.cpp b/source/compiler-core/slang-artifact-associated-impl.cpp index f29c0f596f..07d69bf8ea 100644 --- a/source/compiler-core/slang-artifact-associated-impl.cpp +++ b/source/compiler-core/slang-artifact-associated-impl.cpp @@ -313,4 +313,24 @@ Slice ArtifactPostEmitMetadata::getExportedFunctionMangledNames() return Slice(m_exportedFunctionMangledNames.getBuffer(), m_exportedFunctionMangledNames.getCount()); } +SlangResult ArtifactPostEmitMetadata::isParameterLocationUsed( + SlangParameterCategory category, + SlangUInt spaceIndex, + SlangUInt registerIndex, + bool& outUsed) +{ + for (const auto& range : getUsedBindingRanges()) + { + if (range.containsBinding((slang::ParameterCategory)category, spaceIndex, registerIndex)) + { + outUsed = true; + return SLANG_OK; + } + } + + outUsed = false; + return SLANG_OK; +} + + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-associated-impl.h b/source/compiler-core/slang-artifact-associated-impl.h index a6e323b0a1..d114986049 100644 --- a/source/compiler-core/slang-artifact-associated-impl.h +++ b/source/compiler-core/slang-artifact-associated-impl.h @@ -134,6 +134,7 @@ struct ShaderBindingRange case slang::ShaderResource: case slang::UnorderedAccess: case slang::SamplerState: + case slang::DescriptorTableSlot: return true; default: return false; @@ -157,6 +158,13 @@ class ArtifactPostEmitMetadata : public ComBaseObject, public IArtifactPostEmitM SLANG_NO_THROW virtual Slice SLANG_MCALL getUsedBindingRanges() SLANG_OVERRIDE; SLANG_NO_THROW virtual Slice SLANG_MCALL getExportedFunctionMangledNames() SLANG_OVERRIDE; + // IMetadata + SLANG_NO_THROW virtual SlangResult SLANG_MCALL isParameterLocationUsed( + SlangParameterCategory category, // is this a `t` register? `s` register? + SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan + SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan + bool& outUsed) SLANG_OVERRIDE; + void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); diff --git a/source/compiler-core/slang-artifact-associated.h b/source/compiler-core/slang-artifact-associated.h index 7664942713..91ae09aab8 100644 --- a/source/compiler-core/slang-artifact-associated.h +++ b/source/compiler-core/slang-artifact-associated.h @@ -117,7 +117,7 @@ class IArtifactDiagnostics : public IClonable struct ShaderBindingRange; -class IArtifactPostEmitMetadata : public ICastable +class IArtifactPostEmitMetadata : public slang::IMetadata { public: SLANG_COM_INTERFACE(0x5d03bce9, 0xafb1, 0x4fc8, { 0xa4, 0x6f, 0x3c, 0xe0, 0x7b, 0x6, 0x1b, 0x1b }); diff --git a/source/slang-record-replay/record/slang-component-type.cpp b/source/slang-record-replay/record/slang-component-type.cpp index 5ebf735747..bc38acfae1 100644 --- a/source/slang-record-replay/record/slang-component-type.cpp +++ b/source/slang-record-replay/record/slang-component-type.cpp @@ -127,6 +127,25 @@ namespace SlangRecord return res; } + SLANG_NO_THROW SlangResult SLANG_MCALL IComponentTypeRecorder::getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) + { + // No need to record this call. + return m_actualComponentType->getEntryPointMetadata(entryPointIndex, targetIndex, outMetadata, outDiagnostics); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL IComponentTypeRecorder::getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) + { + // No need to record this call. + return m_actualComponentType->getTargetMetadata(targetIndex, outMetadata, outDiagnostics); + } + SLANG_NO_THROW SlangResult IComponentTypeRecorder::getResultAsFileSystem( SlangInt entryPointIndex, SlangInt targetIndex, diff --git a/source/slang-record-replay/record/slang-component-type.h b/source/slang-record-replay/record/slang-component-type.h index 110733044a..52e07d9c0f 100644 --- a/source/slang-record-replay/record/slang-component-type.h +++ b/source/slang-record-replay/record/slang-component-type.h @@ -61,6 +61,15 @@ namespace SlangRecord SlangInt targetIndex, slang::IBlob** outCode, slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics = nullptr) override; protected: virtual ApiClassId getClassId() = 0; virtual SessionRecorder* getSessionRecorder() = 0; diff --git a/source/slang-record-replay/record/slang-entrypoint.h b/source/slang-record-replay/record/slang-entrypoint.h index abe2dc9c09..29a3329fee 100644 --- a/source/slang-record-replay/record/slang-entrypoint.h +++ b/source/slang-record-replay/record/slang-entrypoint.h @@ -69,6 +69,23 @@ namespace SlangRecord return Super::getTargetCode(targetIndex, outCode, outDiagnostics); } + SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getEntryPointMetadata(entryPointIndex, targetIndex, outMetadata, outDiagnostics); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getTargetMetadata(targetIndex, outMetadata, outDiagnostics); + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( SlangInt entryPointIndex, SlangInt targetIndex, diff --git a/source/slang-record-replay/record/slang-module.h b/source/slang-record-replay/record/slang-module.h index e793bea986..ce009eac80 100644 --- a/source/slang-record-replay/record/slang-module.h +++ b/source/slang-record-replay/record/slang-module.h @@ -85,6 +85,23 @@ namespace SlangRecord return Super::getTargetCode(targetIndex, outCode, outDiagnostics); } + SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getEntryPointMetadata(entryPointIndex, targetIndex, outMetadata, outDiagnostics); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getTargetMetadata(targetIndex, outMetadata, outDiagnostics); + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( SlangInt entryPointIndex, SlangInt targetIndex, diff --git a/source/slang-record-replay/record/slang-type-conformance.h b/source/slang-record-replay/record/slang-type-conformance.h index d1dfb3238b..6c6889d022 100644 --- a/source/slang-record-replay/record/slang-type-conformance.h +++ b/source/slang-record-replay/record/slang-type-conformance.h @@ -65,6 +65,23 @@ namespace SlangRecord return Super::getTargetCode(targetIndex, outCode, outDiagnostics); } + SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getEntryPointMetadata(entryPointIndex, targetIndex, outMetadata, outDiagnostics); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getTargetMetadata(targetIndex, outMetadata, outDiagnostics); + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( SlangInt entryPointIndex, SlangInt targetIndex, diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 820cab03f3..17501163f7 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -317,10 +317,22 @@ namespace Slang SlangInt targetIndex, slang::IBlob** outCode, slang::IBlob** outDiagnostics) SLANG_OVERRIDE; + + IArtifact* getTargetArtifact(SlangInt targetIndex, slang::IBlob** outDiagnostics); + SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCode( SlangInt targetIndex, slang::IBlob** outCode, slang::IBlob** outDiagnostics = nullptr) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics = nullptr) SLANG_OVERRIDE; SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( SlangInt entryPointIndex, @@ -580,6 +592,8 @@ namespace Slang Scope* m_lookupScope = nullptr; std::unique_ptr> m_mapMangledNameToIntVal; + + Dictionary> m_targetArtifacts; }; /// A component type built up from other component types. @@ -914,6 +928,23 @@ namespace Slang return Super::getTargetCode(targetIndex, outCode, outDiagnostics); } + SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getEntryPointMetadata(entryPointIndex, targetIndex, outMetadata, outDiagnostics); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getTargetMetadata(targetIndex, outMetadata, outDiagnostics); + } + SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( SlangInt entryPointIndex, SlangInt targetIndex, @@ -1159,6 +1190,23 @@ namespace Slang return Super::getTargetCode(targetIndex, outCode, outDiagnostics); } + SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getEntryPointMetadata(entryPointIndex, targetIndex, outMetadata, outDiagnostics); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getTargetMetadata(targetIndex, outMetadata, outDiagnostics); + } + SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( SlangInt entryPointIndex, SlangInt targetIndex, @@ -1460,6 +1508,23 @@ namespace Slang return Super::getEntryPointHash(entryPointIndex, targetIndex, outHash); } + SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getEntryPointMetadata(entryPointIndex, targetIndex, outMetadata, outDiagnostics); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) SLANG_OVERRIDE + { + return Super::getTargetMetadata(targetIndex, outMetadata, outDiagnostics); + } + /// Get a serialized representation of the checked module. virtual SLANG_NO_THROW SlangResult SLANG_MCALL serialize(ISlangBlob** outSerializedBlob) override; diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index ea22cbcba0..5d3331c6fa 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -1225,10 +1225,6 @@ static void addExplicitParameterBindings_GLSL( } } - // We use the HLSL binding directly (even though this notionally for GLSL/Vulkan) - // We'll do the shifting at later later point in _maybeApplyHLSLToVulkanShifts - info[kResInfo].resInfo = typeLayout->findOrAddResourceInfo(hlslInfo.kind); - if (warnedMissingVulkanLayoutModifier) { // If we warn due to invalid bindings and user did not set how to interpret 'hlsl style bindings', we should map @@ -1236,7 +1232,7 @@ static void addExplicitParameterBindings_GLSL( if(!hlslToVulkanLayoutOptions || hlslToVulkanLayoutOptions->getKindShiftEnabledFlags() == HLSLToVulkanLayoutOptions::KindFlag::None) { - info[kResInfo].resInfo->kind = LayoutResourceKind::DescriptorTableSlot; + info[kResInfo].resInfo = typeLayout->findOrAddResourceInfo(LayoutResourceKind::DescriptorTableSlot); info[kResInfo].resInfo->count = 1; } else @@ -1245,6 +1241,11 @@ static void addExplicitParameterBindings_GLSL( } } + // We use the HLSL binding directly (even though this notionally for GLSL/Vulkan) + // We'll do the shifting at later later point in _maybeApplyHLSLToVulkanShifts + if (!info[kResInfo].resInfo) + info[kResInfo].resInfo = typeLayout->findOrAddResourceInfo(hlslInfo.kind); + info[kResInfo].semanticInfo.kind = info[kResInfo].resInfo->kind; info[kResInfo].semanticInfo.index = UInt(hlslInfo.index); info[kResInfo].semanticInfo.space = UInt(hlslInfo.space); diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index dc5f9a7550..c9717272b0 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -4704,6 +4704,38 @@ SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointHostCallable( return artifact->loadSharedLibrary(ArtifactKeep::Yes, outSharedLibrary); } +SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointMetadata( + SlangInt entryPointIndex, + Int targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) +{ + auto linkage = getLinkage(); + if (targetIndex < 0 || targetIndex >= linkage->targets.getCount()) + return SLANG_E_INVALID_ARG; + auto target = linkage->targets[targetIndex]; + + auto targetProgram = getTargetProgram(target); + + DiagnosticSink sink(linkage->getSourceManager(), Lexer::sourceLocationLexer); + applySettingsToDiagnosticSink(&sink, &sink, linkage->m_optionSet); + applySettingsToDiagnosticSink(&sink, &sink, m_optionSet); + + IArtifact* artifact = targetProgram->getOrCreateEntryPointResult(entryPointIndex, &sink); + sink.getBlobIfNeeded(outDiagnostics); + + if (artifact == nullptr) + return SLANG_E_NOT_AVAILABLE; + + auto metadata = findAssociatedRepresentation(artifact); + if (!metadata) + return SLANG_E_NOT_AVAILABLE; + + *outMetadata = static_cast(metadata); + (*outMetadata)->addRef(); + return SLANG_OK; +} + RefPtr ComponentType::specialize( SpecializationArg const* inSpecializationArgs, SlangInt specializationArgCount, @@ -4933,14 +4965,16 @@ void ComponentType::enumerateIRModules(EnumerateIRModulesCallback callback, void acceptVisitor(&visitor, nullptr); } -SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getTargetCode( - Int targetIndex, - slang::IBlob** outCode, - slang::IBlob** outDiagnostics) +IArtifact* ComponentType::getTargetArtifact(Int targetIndex, slang::IBlob** outDiagnostics) { auto linkage = getLinkage(); if (targetIndex < 0 || targetIndex >= linkage->targets.getCount()) - return SLANG_E_INVALID_ARG; + return nullptr; + ComPtr artifact; + if (m_targetArtifacts.tryGetValue(targetIndex, artifact)) + { + return artifact.get(); + } // If the user hasn't specified any entry points, then we should // discover all entrypoints that are defined in linked modules, and @@ -4964,8 +4998,13 @@ SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getTargetCode( } RefPtr composite = new CompositeComponentType(linkage, components); ComPtr linkedComponentType; - SLANG_RETURN_ON_FAIL(composite->link(linkedComponentType.writeRef(), outDiagnostics)); - return linkedComponentType->getTargetCode(targetIndex, outCode, outDiagnostics); + SLANG_RETURN_NULL_ON_FAIL(composite->link(linkedComponentType.writeRef(), outDiagnostics)); + auto targetArtifact = static_cast(linkedComponentType.get())->getTargetArtifact(targetIndex, outDiagnostics); + if (targetArtifact) + { + m_targetArtifacts[targetIndex] = targetArtifact; + } + return targetArtifact; } auto target = linkage->targets[targetIndex]; @@ -4975,8 +5014,18 @@ SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getTargetCode( applySettingsToDiagnosticSink(&sink, &sink, linkage->m_optionSet); applySettingsToDiagnosticSink(&sink, &sink, m_optionSet); - IArtifact* artifact = targetProgram->getOrCreateWholeProgramResult(&sink); + IArtifact* targetArtifact = targetProgram->getOrCreateWholeProgramResult(&sink); sink.getBlobIfNeeded(outDiagnostics); + m_targetArtifacts[targetIndex] = ComPtr(targetArtifact); + return targetArtifact; +} + +SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getTargetCode( + Int targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) +{ + IArtifact* artifact = getTargetArtifact(targetIndex, outDiagnostics); if (artifact == nullptr) return SLANG_FAIL; @@ -4984,6 +5033,24 @@ SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getTargetCode( return artifact->loadBlob(ArtifactKeep::Yes, outCode); } +SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getTargetMetadata( + Int targetIndex, + slang::IMetadata** outMetadata, + slang::IBlob** outDiagnostics) +{ + IArtifact* artifact = getTargetArtifact(targetIndex, outDiagnostics); + + if (artifact == nullptr) + return SLANG_FAIL; + + auto metadata = findAssociatedRepresentation(artifact); + if (!metadata) + return SLANG_E_NOT_AVAILABLE; + *outMetadata = static_cast(metadata); + (*outMetadata)->addRef(); + return SLANG_OK; +} + // // CompositeComponentType // @@ -6888,19 +6955,7 @@ SlangResult EndToEndCompileRequest::isParameterLocationUsed(Int entryPointIndex, if (!metadata) return SLANG_E_NOT_AVAILABLE; - - // TODO: optimize this with a binary search through a sorted list - for (const auto& range : metadata->getUsedBindingRanges()) - { - if (range.containsBinding((slang::ParameterCategory)category, spaceIndex, registerIndex)) - { - outUsed = true; - return SLANG_OK; - } - } - - outUsed = false; - return SLANG_OK; + return metadata->isParameterLocationUsed(category, spaceIndex, registerIndex, outUsed); } } // namespace Slang diff --git a/tests/bindings/hlsl-to-vulkan-combined.hlsl.expected b/tests/bindings/hlsl-to-vulkan-combined.hlsl.expected index de67a3592b..7466a276dc 100644 --- a/tests/bindings/hlsl-to-vulkan-combined.hlsl.expected +++ b/tests/bindings/hlsl-to-vulkan-combined.hlsl.expected @@ -41,11 +41,11 @@ standard output = { "bindings": [ { "name": "t0", - "binding": {"kind": "descriptorTableSlot", "index": 0} + "binding": {"kind": "descriptorTableSlot", "index": 0, "used": 0} }, { "name": "t1", - "binding": {"kind": "descriptorTableSlot", "index": 1} + "binding": {"kind": "descriptorTableSlot", "index": 1, "used": 0} } ] } diff --git a/tests/bindings/hlsl-to-vulkan-global.hlsl.expected b/tests/bindings/hlsl-to-vulkan-global.hlsl.expected index b0b8f6a17a..e0e0db8327 100644 --- a/tests/bindings/hlsl-to-vulkan-global.hlsl.expected +++ b/tests/bindings/hlsl-to-vulkan-global.hlsl.expected @@ -64,11 +64,11 @@ standard output = { }, { "name": "t", - "binding": {"kind": "descriptorTableSlot", "index": 0} + "binding": {"kind": "descriptorTableSlot", "index": 0, "used": 1} }, { "name": "sampler", - "binding": {"kind": "descriptorTableSlot", "index": 1} + "binding": {"kind": "descriptorTableSlot", "index": 1, "used": 1} } ] } diff --git a/tests/slang-extension/dynamic-resource-gl.slang.1.expected b/tests/slang-extension/dynamic-resource-gl.slang.1.expected index fe48e643a7..703cb1229a 100644 --- a/tests/slang-extension/dynamic-resource-gl.slang.1.expected +++ b/tests/slang-extension/dynamic-resource-gl.slang.1.expected @@ -70,23 +70,23 @@ standard output = { "bindings": [ { "name": "g_TextureHeap", - "binding": {"kind": "descriptorTableSlot", "space": 1, "index": 0} + "binding": {"kind": "descriptorTableSlot", "space": 1, "index": 0, "used": 1} }, { "name": "g_SamplerHeap", - "binding": {"kind": "descriptorTableSlot", "space": 1, "index": 2} + "binding": {"kind": "descriptorTableSlot", "space": 1, "index": 2, "used": 1} }, { "name": "g_SingleDynamicResourceA", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 0} + "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 0, "used": 1} }, { "name": "g_SingleDynamicResourceB", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 1} + "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 1, "used": 1} }, { "name": "g_SingleDynamicResourceC", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 2} + "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 2, "used": 1} } ] } diff --git a/tools/slang-unit-test/unit-test-image-format-reflection.cpp b/tools/slang-unit-test/unit-test-image-format-reflection.cpp index 2ada598b4c..34678472c8 100644 --- a/tools/slang-unit-test/unit-test-image-format-reflection.cpp +++ b/tools/slang-unit-test/unit-test-image-format-reflection.cpp @@ -1,4 +1,4 @@ -// unit-test-translation-unit-import.cpp +// unit-test-image-format-reflection.cpp #include "slang.h" diff --git a/tools/slang-unit-test/unit-test-parameter-usage-reflection.cpp b/tools/slang-unit-test/unit-test-parameter-usage-reflection.cpp new file mode 100644 index 0000000000..911bdc5a43 --- /dev/null +++ b/tools/slang-unit-test/unit-test-parameter-usage-reflection.cpp @@ -0,0 +1,68 @@ +// unit-test-parameter-usage-reflection.cpp + +#include "slang.h" + +#include +#include + +#include "tools/unit-test/slang-unit-test.h" +#include "slang-com-ptr.h" +#include "../../source/core/slang-io.h" +#include "../../source/core/slang-process.h" + +using namespace Slang; + +// Test that the isParameterLocationUsed API works. + +SLANG_UNIT_TEST(isParameterLocationUsedReflection) +{ + // Source for a module that contains an undecorated entrypoint. + const char* userSourceBody = R"( + Texture2D g_tex : register(t0); + [shader("fragment")] + float4 fragMain(float4 pos:SV_Position) : SV_Target + { + return g_tex.Load(int3(0, 0, 0)); + } + )"; + + auto moduleName = "moduleG" + String(Process::getId()); + String userSource = "import " + moduleName + ";\n" + userSourceBody; + ComPtr globalSession; + SLANG_CHECK(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef()) == SLANG_OK); + slang::TargetDesc targetDesc = {}; + targetDesc.format = SLANG_SPIRV; + targetDesc.profile = globalSession->findProfile("spirv_1_5"); + slang::SessionDesc sessionDesc = {}; + sessionDesc.targetCount = 1; + sessionDesc.targets = &targetDesc; + ComPtr session; + SLANG_CHECK(globalSession->createSession(sessionDesc, session.writeRef()) == SLANG_OK); + + ComPtr diagnosticBlob; + auto module = session->loadModuleFromSourceString("m", "m.slang", userSourceBody, diagnosticBlob.writeRef()); + SLANG_CHECK(module != nullptr); + + ComPtr entryPoint; + module->findAndCheckEntryPoint("fragMain", SLANG_STAGE_FRAGMENT, entryPoint.writeRef(), diagnosticBlob.writeRef()); + SLANG_CHECK(entryPoint != nullptr); + + ComPtr compositeProgram; + slang::IComponentType* components[] = { module, entryPoint.get() }; + session->createCompositeComponentType(components, 2, compositeProgram.writeRef(), diagnosticBlob.writeRef()); + SLANG_CHECK(compositeProgram != nullptr); + + ComPtr linkedProgram; + compositeProgram->link(linkedProgram.writeRef(), nullptr); + + ComPtr metadata; + linkedProgram->getTargetMetadata(0, metadata.writeRef(), nullptr); + + bool isUsed = false; + metadata->isParameterLocationUsed(SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT, 0, 0, isUsed); + SLANG_CHECK(isUsed); + + metadata->isParameterLocationUsed(SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT, 0, 1, isUsed); + SLANG_CHECK(!isUsed); +} +