summaryrefslogtreecommitdiff
path: root/source/slang
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/slang-api.cpp7
-rw-r--r--source/slang/slang-compiler.cpp56
-rwxr-xr-xsource/slang/slang-compiler.h115
-rw-r--r--source/slang/slang-emit.cpp14
-rw-r--r--source/slang/slang-ir-collect-global-uniforms.cpp36
-rw-r--r--source/slang/slang-ir-link.h1
-rw-r--r--source/slang/slang-ir-metadata.cpp77
-rw-r--r--source/slang/slang-ir-metadata.h12
-rw-r--r--source/slang/slang-reflection-api.cpp14
-rw-r--r--source/slang/slang.cpp15
10 files changed, 304 insertions, 43 deletions
diff --git a/source/slang/slang-api.cpp b/source/slang/slang-api.cpp
index 911bd0f0f..50986660b 100644
--- a/source/slang/slang-api.cpp
+++ b/source/slang/slang-api.cpp
@@ -245,6 +245,13 @@ SLANG_API void spSetCompileFlags(
request->setCompileFlags(flags);
}
+SLANG_API SlangCompileFlags spGetCompileFlags(
+ slang::ICompileRequest* request)
+{
+ SLANG_ASSERT(request);
+ return request->getCompileFlags();
+}
+
SLANG_API void spSetDumpIntermediates(
slang::ICompileRequest* request,
int enable)
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 7988af3e8..74162d2ef 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -143,6 +143,28 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
return SLANG_OK;
}
+ SlangResult CompileResult::isParameterLocationUsed(SlangParameterCategory category, UInt spaceIndex, UInt registerIndex, bool& outUsed)
+ {
+ if (!postEmitMetadata)
+ return SLANG_E_NOT_AVAILABLE;
+
+ if (!ShaderBindingRange::isUsageTracked((slang::ParameterCategory)category))
+ return SLANG_E_NOT_AVAILABLE;
+
+ // TODO: optimize this with a binary search through a sorted list
+ for (const auto& range : postEmitMetadata->usedBindings)
+ {
+ if (range.containsBinding((slang::ParameterCategory)category, spaceIndex, registerIndex))
+ {
+ outUsed = true;
+ return SLANG_OK;
+ }
+ }
+
+ outUsed = false;
+ return SLANG_OK;
+ }
+
//
// FrontEndEntryPointRequest
//
@@ -662,7 +684,8 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
}
SlangResult CodeGenContext::emitEntryPointsSource(
- String& outSource)
+ String& outSource,
+ RefPtr<PostEmitMetadata>& outMetadata)
{
outSource = String();
@@ -714,7 +737,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
else
{
return emitEntryPointsSourceFromIR(
- outSource);
+ outSource, outMetadata);
}
}
@@ -985,7 +1008,8 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
}
SlangResult CodeGenContext::emitWithDownstreamForEntryPoints(
- RefPtr<DownstreamCompileResult>& outResult)
+ RefPtr<DownstreamCompileResult>& outResult,
+ RefPtr<PostEmitMetadata>& outMetadata)
{
outResult.setNull();
@@ -1127,7 +1151,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
options.sourceContentsPath = calcSourcePathForEntryPoints();
CodeGenContext sourceCodeGenContext(this, sourceTarget, extensionTracker);
- SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(options.sourceContents));
+ SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(options.sourceContents, outMetadata));
}
else
{
@@ -1144,7 +1168,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
else
{
CodeGenContext sourceCodeGenContext(this, sourceTarget, extensionTracker);
- SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(options.sourceContents));
+ SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(options.sourceContents, outMetadata));
sourceCodeGenContext.maybeDumpIntermediate(options.sourceContents.getBuffer());
sourceLanguage = (SourceLanguage)TypeConvertUtil::getSourceLanguageFromTarget((SlangCompileTarget)sourceTarget);
@@ -1504,7 +1528,8 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
SlangResult emitSPIRVForEntryPointsDirectly(
CodeGenContext* codeGenContext,
- List<uint8_t>& spirvOut);
+ List<uint8_t>& spirvOut,
+ RefPtr<PostEmitMetadata>& outMetadata);
static CodeGenTarget _getIntermediateTarget(CodeGenTarget target)
{
@@ -1519,7 +1544,8 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
/// Function to simplify the logic around emitting, and dissassembling
SlangResult CodeGenContext::_emitEntryPoints(
- RefPtr<DownstreamCompileResult>& outDownstreamResult)
+ RefPtr<DownstreamCompileResult>& outDownstreamResult,
+ RefPtr<PostEmitMetadata>& outMetadata)
{
auto target = getTargetFormat();
switch (target)
@@ -1533,7 +1559,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
CodeGenContext intermediateContext(this, intermediateTarget);
RefPtr<DownstreamCompileResult> code;
- SLANG_RETURN_ON_FAIL(intermediateContext._emitEntryPoints(code));
+ SLANG_RETURN_ON_FAIL(intermediateContext._emitEntryPoints(code, outMetadata));
intermediateContext.maybeDumpIntermediate(code);
// Then disassemble the intermediate binary result to get the desired output
@@ -1548,7 +1574,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
if (getTargetReq()->shouldEmitSPIRVDirectly())
{
List<uint8_t> spirv;
- SLANG_RETURN_ON_FAIL(emitSPIRVForEntryPointsDirectly(this, spirv));
+ SLANG_RETURN_ON_FAIL(emitSPIRVForEntryPointsDirectly(this, spirv, outMetadata));
auto spirvBlob = ListBlob::moveCreate(spirv);
outDownstreamResult = new BlobDownstreamCompileResult(DownstreamDiagnostics(), spirvBlob);
return SLANG_OK;
@@ -1560,7 +1586,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::ShaderSharedLibrary:
case CodeGenTarget::HostExecutable:
- SLANG_RETURN_ON_FAIL(emitWithDownstreamForEntryPoints(outDownstreamResult));
+ SLANG_RETURN_ON_FAIL(emitWithDownstreamForEntryPoints(outDownstreamResult, outMetadata));
return SLANG_OK;
default: break;
@@ -1590,11 +1616,12 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
case CodeGenTarget::HostExecutable:
{
RefPtr<DownstreamCompileResult> downstreamResult;
+ RefPtr<PostEmitMetadata> metadata;
- if (SLANG_SUCCEEDED(_emitEntryPoints(downstreamResult)))
+ if (SLANG_SUCCEEDED(_emitEntryPoints(downstreamResult, metadata)))
{
maybeDumpIntermediate(downstreamResult);
- result = CompileResult(downstreamResult);
+ result = CompileResult(downstreamResult, metadata);
}
}
break;
@@ -1606,17 +1633,18 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
case CodeGenTarget::CSource:
{
RefPtr<ExtensionTracker> extensionTracker = _newExtensionTracker(target);
+ RefPtr<PostEmitMetadata> metadata;
CodeGenContext subContext(this, target, extensionTracker);
String code;
- if (SLANG_FAILED(subContext.emitEntryPointsSource(code)))
+ if (SLANG_FAILED(subContext.emitEntryPointsSource(code, metadata)))
{
return result;
}
subContext.maybeDumpIntermediate(code.getBuffer());
- result = CompileResult(code);
+ result = CompileResult(code, metadata);
}
break;
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 39ee830d2..e0152566c 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -141,26 +141,117 @@ namespace Slang
class Module;
class TranslationUnitRequest;
+ struct ShaderBindingRange
+ {
+ slang::ParameterCategory category = slang::ParameterCategory::None;
+ UInt spaceIndex = 0;
+ UInt registerIndex = 0;
+ UInt registerCount = 0; // 0 for unsized
+
+ bool isInfinite() const
+ {
+ return registerCount == 0;
+ }
+
+ bool containsBinding(slang::ParameterCategory _category, UInt _spaceIndex, UInt _registerIndex) const
+ {
+ return category == _category
+ && spaceIndex == _spaceIndex
+ && registerIndex <= _registerIndex
+ && (isInfinite() || registerCount + registerIndex > _registerIndex);
+ }
+
+ bool intersectsWith(const ShaderBindingRange& other) const
+ {
+ if (category != other.category || spaceIndex != other.spaceIndex)
+ return false;
+
+ const bool leftIntersection = (registerIndex < other.registerIndex + other.registerCount) || other.isInfinite();
+ const bool rightIntersection = (other.registerIndex < registerIndex + registerCount) || isInfinite();
+
+ return leftIntersection && rightIntersection;
+ }
+
+ bool adjacentTo(const ShaderBindingRange& other) const
+ {
+ if (category != other.category || spaceIndex != other.spaceIndex)
+ return false;
+
+ const bool leftIntersection = (registerIndex <= other.registerIndex + other.registerCount) || other.isInfinite();
+ const bool rightIntersection = (other.registerIndex <= registerIndex + registerCount) || isInfinite();
+
+ return leftIntersection && rightIntersection;
+ }
+
+ void mergeWith(const ShaderBindingRange other)
+ {
+ UInt newRegisterIndex = Math::Min(registerIndex, other.registerIndex);
+
+ if (other.isInfinite())
+ registerCount = 0;
+ else if (!isInfinite())
+ registerCount = Math::Max(registerIndex + registerCount, other.registerIndex + other.registerCount) - newRegisterIndex;
+
+ registerIndex = newRegisterIndex;
+ }
+
+ static bool isUsageTracked(slang::ParameterCategory category)
+ {
+ switch(category)
+ {
+ case slang::ConstantBuffer:
+ case slang::ShaderResource:
+ case slang::UnorderedAccess:
+ case slang::SamplerState:
+ return true;
+ default:
+ return false;
+ }
+ }
+ };
+
+ struct PostEmitMetadata : public RefObject
+ {
+ List<ShaderBindingRange> usedBindings;
+ };
+
// Result of compiling an entry point.
// Should only ever be string, binary or shared library
class CompileResult
{
public:
CompileResult() = default;
- explicit CompileResult(String const& str) : format(ResultFormat::Text), outputString(str) {}
- explicit CompileResult(ISlangBlob* inBlob) : format(ResultFormat::Binary), blob(inBlob) {}
- explicit CompileResult(DownstreamCompileResult* inDownstreamResult): format(ResultFormat::Binary), downstreamResult(inDownstreamResult) {}
- explicit CompileResult(const UnownedStringSlice& slice ) : format(ResultFormat::Text), outputString(slice) {}
+ explicit CompileResult(String const& str, RefPtr<PostEmitMetadata> metadata)
+ : format(ResultFormat::Text)
+ , outputString(str)
+ , postEmitMetadata(metadata) {}
+
+ explicit CompileResult(ISlangBlob* inBlob)
+ : format(ResultFormat::Binary)
+ , blob(inBlob) {}
+
+ explicit CompileResult(DownstreamCompileResult* inDownstreamResult, RefPtr<PostEmitMetadata> metadata)
+ : format(ResultFormat::Binary)
+ , downstreamResult(inDownstreamResult)
+ , postEmitMetadata(metadata) {}
+
+ explicit CompileResult(const UnownedStringSlice& slice )
+ : format(ResultFormat::Text)
+ , outputString(slice) {}
SlangResult getBlob(ComPtr<ISlangBlob>& outBlob) const;
SlangResult getSharedLibrary(ComPtr<ISlangSharedLibrary>& outSharedLibrary);
+ SlangResult isParameterLocationUsed(SlangParameterCategory category, UInt spaceIndex, UInt registerIndex, bool& outUsed);
+
ResultFormat format = ResultFormat::None;
String outputString; ///< Only set if result type is ResultFormat::Text
mutable ComPtr<ISlangBlob> blob;
RefPtr<DownstreamCompileResult> downstreamResult;
+
+ RefPtr<PostEmitMetadata> postEmitMetadata;
};
/// Information collected about global or entry-point shader parameters
@@ -939,7 +1030,7 @@ namespace Slang
Index getShaderParamCount() SLANG_OVERRIDE { return 0; }
ShaderParamInfo getShaderParam(Index index) SLANG_OVERRIDE { SLANG_UNUSED(index); return ShaderParamInfo(); }
-
+
class EntryPointSpecializationInfo : public SpecializationInfo
{
public:
@@ -2428,13 +2519,16 @@ namespace Slang
/* Emits entry point source taking into account if a pass-through or not. Uses 'targetFormat' to determine
the target (not targetReq) */
SlangResult emitEntryPointsSource(
- String& outSource);
+ String& outSource,
+ RefPtr<PostEmitMetadata>& outMetadata);
SlangResult emitEntryPointsSourceFromIR(
- String& outSource);
+ String& outSource,
+ RefPtr<PostEmitMetadata>& outMetadata);
SlangResult emitWithDownstreamForEntryPoints(
- RefPtr<DownstreamCompileResult>& outResult);
+ RefPtr<DownstreamCompileResult>& outResult,
+ RefPtr<PostEmitMetadata>& outMetadata);
/* Determines a suitable filename to identify the input for a given entry point being compiled.
If the end-to-end compile is a pass-through case, will attempt to find the (unique) source file
@@ -2450,7 +2544,8 @@ namespace Slang
SlangResult _emitEntryPoints(
- RefPtr<DownstreamCompileResult>& outDownstreamResult);
+ RefPtr<DownstreamCompileResult>& outDownstreamResult,
+ RefPtr<PostEmitMetadata>& outMetadata);
private:
Shared* m_shared = nullptr;
@@ -2477,6 +2572,7 @@ namespace Slang
// slang::ICompileRequest
virtual SLANG_NO_THROW void SLANG_MCALL setFileSystem(ISlangFileSystem* fileSystem) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setCompileFlags(SlangCompileFlags flags) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangCompileFlags SLANG_MCALL getCompileFlags() SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediates(int enable) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediatePrefix(const char* prefix) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setLineDirectiveMode(SlangLineDirectiveMode mode) SLANG_OVERRIDE;
@@ -2536,6 +2632,7 @@ namespace Slang
virtual SLANG_NO_THROW void SLANG_MCALL setCommandLineCompilerMode() SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL addTargetCapability(SlangInt targetIndex, SlangCapabilityID capability) SLANG_OVERRIDE;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL getProgramWithEntryPoints(slang::IComponentType** outProgram) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL isParameterLocationUsed(SlangInt entryPointIndex, SlangInt targetIndex, SlangParameterCategory category, SlangUInt spaceIndex, SlangUInt registerIndex, bool& outUsed) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setTargetLineDirectiveMode(
SlangInt targetIndex,
SlangLineDirectiveMode mode) SLANG_OVERRIDE;
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index d231acf14..a128644d3 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -25,6 +25,7 @@
#include "slang-ir-lower-tuple-types.h"
#include "slang-ir-lower-bit-cast.h"
#include "slang-ir-lower-reinterpret.h"
+#include "slang-ir-metadata.h"
#include "slang-ir-optix-entry-point-uniforms.h"
#include "slang-ir-restructure.h"
#include "slang-ir-restructure-scoping.h"
@@ -818,11 +819,15 @@ Result linkAndOptimizeIR(
#endif
validateIRModuleIfEnabled(codeGenContext, irModule);
+ outLinkedIR.metadata = new PostEmitMetadata();
+ collectMetadata(irModule, *outLinkedIR.metadata);
+
return SLANG_OK;
}
SlangResult CodeGenContext::emitEntryPointsSourceFromIR(
- String& outSource)
+ String& outSource,
+ RefPtr<PostEmitMetadata>& outMetadata)
{
outSource = String();
@@ -927,6 +932,8 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR(
auto irModule = linkedIR.module;
+ outMetadata = linkedIR.metadata;
+
// After all of the required optimization and legalization
// passes have been performed, we can emit target code from
// the IR module.
@@ -1007,7 +1014,8 @@ SlangResult emitSPIRVFromIR(
SlangResult emitSPIRVForEntryPointsDirectly(
CodeGenContext* codeGenContext,
- List<uint8_t>& spirvOut)
+ List<uint8_t>& spirvOut,
+ RefPtr<PostEmitMetadata>& outMetadata)
{
// Outside because we want to keep IR in scope whilst we are processing emits
LinkedIR linkedIR;
@@ -1022,6 +1030,8 @@ SlangResult emitSPIRVForEntryPointsDirectly(
emitSPIRVFromIR(codeGenContext, irModule, irEntryPoints, spirvOut);
+ outMetadata = linkedIR.metadata;
+
return SLANG_OK;
}
diff --git a/source/slang/slang-ir-collect-global-uniforms.cpp b/source/slang/slang-ir-collect-global-uniforms.cpp
index 88ebe9940..87b21c819 100644
--- a/source/slang/slang-ir-collect-global-uniforms.cpp
+++ b/source/slang/slang-ir-collect-global-uniforms.cpp
@@ -172,19 +172,6 @@ struct CollectGlobalUniformParametersContext
auto globalParamLayout = fieldLayoutAttr->getLayout();
- // If the given parameter doesn't contribute to uniform/ordinary usage, then
- // we can safely leave it at the global scope and potentially avoid a lot
- // of complications that might otherwise arise (that is, we don't need to worry
- // about downstream passes that might have worked for a simple global parameter,
- // but that would not work for one nested inside a structure.
- //
- // TODO: It would be more consistent and robust to *always* wrap up
- // these global parameters appropriately, and ensure that all the downstream
- // passes can handle that case, since they would need to do so in general.
- //
- if(!globalParamLayout->getTypeLayout()->findSizeAttr(LayoutResourceKind::Uniform) )
- continue;
-
// Once we have decided to do replacement, we need to
// set ourselves up to emit the replacement code.
//
@@ -195,11 +182,6 @@ struct CollectGlobalUniformParametersContext
//
auto fieldKey = builder->createStructKey();
- // The new structure field will need to have whatever decorations
- // had been put on the global parameter (notably including any name hint)
- //
- globalParam->transferDecorationsTo(fieldKey);
-
// In order to make sure that the existing IR layout information for
// the global scope remains valid, we will swap out the key in the
// per-field layout information to reference the key we created
@@ -207,6 +189,24 @@ struct CollectGlobalUniformParametersContext
//
fieldLayoutAttr->setOperand(0, fieldKey);
+ // If the given parameter doesn't contribute to uniform/ordinary usage, then
+ // we can safely leave it at the global scope and potentially avoid a lot
+ // of complications that might otherwise arise (that is, we don't need to worry
+ // about downstream passes that might have worked for a simple global parameter,
+ // but that would not work for one nested inside a structure.
+ //
+ // TODO: It would be more consistent and robust to *always* wrap up
+ // these global parameters appropriately, and ensure that all the downstream
+ // passes can handle that case, since they would need to do so in general.
+ //
+ if (!globalParamLayout->getTypeLayout()->findSizeAttr(LayoutResourceKind::Uniform))
+ continue;
+
+ // The new structure field will need to have whatever decorations
+ // had been put on the global parameter (notably including any name hint)
+ //
+ globalParam->transferDecorationsTo(fieldKey);
+
// Now we can add a field to the `GlobalParams` type that
// will stand in for the parameter: it will have the key we
// just generated, and the type of the original parameter.
diff --git a/source/slang/slang-ir-link.h b/source/slang/slang-ir-link.h
index 6c81ae734..798013a8d 100644
--- a/source/slang/slang-ir-link.h
+++ b/source/slang/slang-ir-link.h
@@ -12,6 +12,7 @@ namespace Slang
RefPtr<IRModule> module;
IRVarLayout* globalScopeVarLayout;
List<IRFunc*> entryPoints;
+ RefPtr<PostEmitMetadata> metadata;
};
diff --git a/source/slang/slang-ir-metadata.cpp b/source/slang/slang-ir-metadata.cpp
new file mode 100644
index 000000000..cc5922e93
--- /dev/null
+++ b/source/slang/slang-ir-metadata.cpp
@@ -0,0 +1,77 @@
+// slang-ir-metadata.cpp
+#include "slang-ir-metadata.h"
+
+#include "slang-ir.h"
+#include "slang-ir-insts.h"
+
+namespace Slang
+{
+
+// This file currently implements a pass that collects information about the shader parameters that
+// are referenced in the IR. It's named 'metadata' in order to support other potential code
+// analysis scenarios in the future.
+
+
+// Inserts a single resource binding (which takes `count` slots, where 0 means unbounded) into the list of resource ranges.
+static void _insertBinding(List<ShaderBindingRange>& ranges, LayoutResourceKind kind, UInt spaceIndex, UInt registerIndex, UInt count)
+{
+ // Construct a new range from the provided resource.
+ ShaderBindingRange newRange;
+ newRange.category = kind;
+ newRange.spaceIndex = spaceIndex;
+ newRange.registerIndex = registerIndex;
+ newRange.registerCount = count;
+
+ // See if the new range is adjacent to any of the existing ranges, merge with that.
+ for (auto& range : ranges)
+ {
+ if (range.adjacentTo(newRange))
+ {
+ range.mergeWith(newRange);
+ return;
+ }
+ }
+
+ // No adjacent ranges found - create a new one.
+ ranges.add(newRange);
+}
+
+// Collects the metadata from the provided IR module, saves it in outMetadata.
+void collectMetadata(const IRModule* irModule, PostEmitMetadata& outMetadata)
+{
+ // Scan the instructions looking for global resource declarations
+ for (const auto& inst : irModule->getGlobalInsts())
+ {
+ auto param = as<IRGlobalParam>(inst);
+ if (!param) continue;
+
+ auto layoutDecoration = param->findDecoration<IRLayoutDecoration>();
+ if (!layoutDecoration) continue;
+
+ auto varLayout = as<IRVarLayout>(layoutDecoration->getLayout());
+ if (!varLayout) continue;
+
+ for(auto sizeAttr : varLayout->getTypeLayout()->getSizeAttrs())
+ {
+ auto kind = sizeAttr->getResourceKind();
+
+ // Only track resource types that we can reliably track, such as textures.
+ // Do not track individual uniforms, for example.
+ if (!ShaderBindingRange::isUsageTracked(kind))
+ continue;
+
+ if (auto offsetAttr = varLayout->findOffsetAttr(kind))
+ {
+ // Get the binding information from this attribute and insert it into the list
+ auto spaceIndex = offsetAttr->getSpace();
+ auto registerIndex = offsetAttr->getOffset();
+ auto size = sizeAttr->getSize();
+ auto count = size.isFinite() ? size.getFiniteValue() : 0;
+ _insertBinding(outMetadata.usedBindings, kind, spaceIndex, registerIndex, count);
+ }
+ }
+ }
+}
+
+
+}
diff --git a/source/slang/slang-ir-metadata.h b/source/slang/slang-ir-metadata.h
new file mode 100644
index 000000000..b7fcd1e2b
--- /dev/null
+++ b/source/slang/slang-ir-metadata.h
@@ -0,0 +1,12 @@
+// slang-ir-metadata.h
+#pragma once
+
+namespace Slang
+{
+
+struct PostEmitMetadata;
+struct IRModule;
+
+void collectMetadata(const IRModule* irModule, PostEmitMetadata& outMetadata);
+
+}
diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp
index 583e000a6..96b1f9004 100644
--- a/source/slang/slang-reflection-api.cpp
+++ b/source/slang/slang-reflection-api.cpp
@@ -2580,6 +2580,20 @@ SLANG_API unsigned spReflectionParameter_GetBindingSpace(SlangReflectionParamete
spReflectionVariableLayout_GetTypeLayout(varLayout)));
}
+SLANG_API SlangResult spIsParameterLocationUsed(
+ SlangCompileRequest* request,
+ SlangInt entryPointIndex,
+ SlangInt targetIndex,
+ SlangParameterCategory category,
+ SlangUInt spaceIndex,
+ SlangUInt registerIndex,
+ bool& outUsed)
+{
+ if (!request)
+ return SLANG_E_INVALID_ARG;
+
+ return request->isParameterLocationUsed(entryPointIndex, targetIndex, category, spaceIndex, registerIndex, outUsed);
+}
// Entry Point Reflection
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 7ce3594e5..7b22d04de 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -4147,6 +4147,11 @@ void EndToEndCompileRequest::setCompileFlags(SlangCompileFlags flags)
getFrontEndReq()->compileFlags = flags;
}
+SlangCompileFlags EndToEndCompileRequest::getCompileFlags()
+{
+ return getFrontEndReq()->compileFlags;
+}
+
void EndToEndCompileRequest::setDumpIntermediates(int enable)
{
shouldDumpIntermediates = (enable != 0);
@@ -4909,4 +4914,14 @@ SlangResult EndToEndCompileRequest::getEntryPoint(SlangInt entryPointIndex, slan
return SLANG_OK;
}
+SlangResult EndToEndCompileRequest::isParameterLocationUsed(Int entryPointIndex, Int targetIndex, SlangParameterCategory category, UInt spaceIndex, UInt registerIndex, bool& outUsed)
+{
+ CompileResult* compileResult = nullptr;
+ if (_getEntryPointResult(this, static_cast<int>(entryPointIndex), static_cast<int>(targetIndex), &compileResult) != SLANG_OK)
+ return SLANG_E_INVALID_ARG;
+
+ return compileResult->isParameterLocationUsed(category, spaceIndex, registerIndex, outUsed);
+}
+
+
} // namespace Slang