summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-type-layout.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2023-07-19 18:35:37 -0400
committerGitHub <noreply@github.com>2023-07-19 15:35:37 -0700
commita5987aad211d2e0b9391bdda4b67873ec9873074 (patch)
treedea1074aa3382c9c047d0102e41a82187426bcf8 /source/slang/slang-type-layout.cpp
parent1cfb1c85b52e00cde2d21874a88cda2c22d18b62 (diff)
Support for vk-shift-* without explicit bindings (#3000)
* Improvements to HLSLToVulkanLayoutOptions. * WIP vk-shift-* with HLSL like binding. Detecting clashes. * Shift example seems to be working correctly. One oddness is that "used" data is now reflected, as we only enable for D3D shader resource types. Now we use those with inferred VK mode they appear. * Implicit seems to work. * Disable inference with Sampler/CombinedTextureSampler. I guess? we could just use the HLSL texture register binding to infer. * Report overlapping ranges in diagnostic. The hlsl-to-vulkan-shift-diagnostic result might be surprising but it is correct, because u is automatically laid out so consumes DescriptorSlot 0, but that's already consumed by c. * First attempt at array layout with infer on Vulkan. * Fix the vulkan shift output. * Array example.
Diffstat (limited to 'source/slang/slang-type-layout.cpp')
-rw-r--r--source/slang/slang-type-layout.cpp132
1 files changed, 107 insertions, 25 deletions
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index c933c5bb5..5cf8d2350 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -696,12 +696,60 @@ struct GLSLSpecializationConstantLayoutRulesImpl : DefaultLayoutRulesImpl
GLSLSpecializationConstantLayoutRulesImpl kGLSLSpecializationConstantLayoutRulesImpl;
-//
+// Given a ShaderParamKind returns the equivalent LayoutResourceKind/ParameterCategory/SlangParameterCategory
+static LayoutResourceKind _getHLSLLayoutResourceKind(ShaderParameterKind kind)
+{
+ switch (kind)
+ {
+ case ShaderParameterKind::ConstantBuffer:
+ return LayoutResourceKind::ConstantBuffer;
+
+ case ShaderParameterKind::TextureUniformBuffer:
+ case ShaderParameterKind::StructuredBuffer:
+ case ShaderParameterKind::RawBuffer:
+ case ShaderParameterKind::Buffer:
+ case ShaderParameterKind::Texture:
+ return LayoutResourceKind::ShaderResource;
+
+ case ShaderParameterKind::MutableStructuredBuffer:
+ case ShaderParameterKind::MutableRawBuffer:
+ case ShaderParameterKind::MutableBuffer:
+ case ShaderParameterKind::MutableTexture:
+ return LayoutResourceKind::UnorderedAccess;
+
+ case ShaderParameterKind::SamplerState:
+ return LayoutResourceKind::SamplerState;
+ default:
+ return LayoutResourceKind::None;
+ }
+}
struct GLSLObjectLayoutRulesImpl : ObjectLayoutRulesImpl
{
- virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind) override
+ virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options& options) override
{
+ if (options.hlslToVulkanKindFlags)
+ {
+ // Is this an HLSL kind that might be shifted
+
+ // Get as hlslLayoutKind
+ const auto hlslLayoutKind = _getHLSLLayoutResourceKind(kind);
+
+ // Get as hlslToVulkanKind
+ const auto hlslToVulkanKind = HLSLToVulkanLayoutOptions::getKind(hlslLayoutKind);
+
+ if (hlslToVulkanKind != HLSLToVulkanLayoutOptions::Kind::Invalid)
+ {
+ // Is this kind enabled for shift?
+ if (options.hlslToVulkanKindFlags & HLSLToVulkanLayoutOptions::getKindFlag(hlslToVulkanKind))
+ {
+ // We are going to consume a HLSL layout kind
+ // Later we will do shifting as necessary
+ return SimpleLayoutInfo(hlslLayoutKind, 1);
+ }
+ }
+ }
+
// In Vulkan GLSL, pretty much every object is just a descriptor-table slot.
// We can refine this method once we support a case where this isn't true.
return SimpleLayoutInfo(LayoutResourceKind::DescriptorTableSlot, 1);
@@ -711,7 +759,7 @@ GLSLObjectLayoutRulesImpl kGLSLObjectLayoutRulesImpl;
struct GLSLPushConstantBufferObjectLayoutRulesImpl : GLSLObjectLayoutRulesImpl
{
- virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind /*kind*/) override
+ virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind /*kind*/, const Options& /* options */) override
{
// Special-case the layout for a constant-buffer, because we don't
// want it to allocate a descriptor-table slot
@@ -722,7 +770,7 @@ GLSLPushConstantBufferObjectLayoutRulesImpl kGLSLPushConstantBufferObjectLayoutR
struct GLSLShaderRecordConstantBufferObjectLayoutRulesImpl : GLSLObjectLayoutRulesImpl
{
- virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind /*kind*/) override
+ virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind /*kind*/, const Options& /* options */) override
{
// Special-case the layout for a constant-buffer, because we don't
// want it to allocate a descriptor-table slot
@@ -733,7 +781,7 @@ GLSLShaderRecordConstantBufferObjectLayoutRulesImpl kGLSLShaderRecordConstantBuf
struct HLSLObjectLayoutRulesImpl : ObjectLayoutRulesImpl
{
- virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) override
+ virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options& /* options */) override
{
switch( kind )
{
@@ -910,7 +958,7 @@ CUDALayoutRulesFamilyImpl kCUDALayoutRulesFamilyImpl;
struct CPUObjectLayoutRulesImpl : ObjectLayoutRulesImpl
{
- virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) override
+ virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options& /* options */) override
{
switch (kind)
{
@@ -962,7 +1010,7 @@ struct CUDAObjectLayoutRulesImpl : CPUObjectLayoutRulesImpl
// of opaque handle (as opposed to a pointer) such as CUsurfObject, CUtexObject
typedef unsigned long long ObjectHandle;
- virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) override
+ virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options & /* options */) override
{
switch (kind)
{
@@ -1501,6 +1549,11 @@ TypeLayoutContext getInitialLayoutContextForTarget(TargetRequest* targetReq, Pro
context.rules = nullptr;
context.matrixLayoutMode = targetReq->getDefaultMatrixLayoutMode();
+ if (auto hlslToVulkanLayoutOptions = targetReq->getHLSLToVulkanLayoutOptions())
+ {
+ context.objectLayoutOptions.hlslToVulkanKindFlags = hlslToVulkanLayoutOptions->getKindShiftEnabledFlags();
+ }
+
if( rulesFamily )
{
context.rules = rulesFamily->getConstantBufferRules(targetReq);
@@ -1586,21 +1639,22 @@ static TypeLayoutResult createSimpleTypeLayout(
return TypeLayoutResult(typeLayout, info);
}
-static SimpleLayoutInfo getParameterGroupLayoutInfo(
- ParameterGroupType* type,
- LayoutRulesImpl* rules)
+static SimpleLayoutInfo _getParameterGroupLayoutInfo(
+ TypeLayoutContext const& context,
+ ParameterGroupType* type,
+ LayoutRulesImpl* rules)
{
if( as<ConstantBufferType>(type) )
{
- return rules->GetObjectLayout(ShaderParameterKind::ConstantBuffer);
+ return rules->GetObjectLayout(ShaderParameterKind::ConstantBuffer, context.objectLayoutOptions);
}
else if( as<TextureBufferType>(type) )
{
- return rules->GetObjectLayout(ShaderParameterKind::TextureUniformBuffer);
+ return rules->GetObjectLayout(ShaderParameterKind::TextureUniformBuffer, context.objectLayoutOptions);
}
else if( as<GLSLShaderStorageBufferType>(type) )
{
- return rules->GetObjectLayout(ShaderParameterKind::ShaderStorageBuffer);
+ return rules->GetObjectLayout(ShaderParameterKind::ShaderStorageBuffer, context.objectLayoutOptions);
}
else if (as<ParameterBlockType>(type))
{
@@ -2270,7 +2324,7 @@ static RefPtr<TypeLayout> _createParameterGroupTypeLayout(
// allocate a constant buffer regiser/binding into
// the overall layout, to account for it.
//
- auto cbUsage = parameterGroupRules->GetObjectLayout(ShaderParameterKind::ConstantBuffer);
+ auto cbUsage = parameterGroupRules->GetObjectLayout(ShaderParameterKind::ConstantBuffer, context.objectLayoutOptions);
containerTypeLayout->addResourceUsage(cbUsage.kind, cbUsage.size);
}
@@ -2730,7 +2784,7 @@ createStructuredBufferTypeLayout(
RefPtr<TypeLayout> elementTypeLayout)
{
auto rules = context.rules;
- auto info = rules->GetObjectLayout(kind);
+ auto info = rules->GetObjectLayout(kind, context.objectLayoutOptions);
auto typeLayout = new StructuredBufferTypeLayout();
@@ -3378,6 +3432,26 @@ RefPtr<TypeLayout> createTypeLayoutForGlobalGenericTypeParam(
return _createTypeLayoutForGlobalGenericTypeParam(context, type, globalGenericParamDecl).layout;
}
+static bool _isDescriptorSlotLike(
+ TypeLayoutContext const& context,
+ LayoutResourceKind kind)
+{
+ if (kind == LayoutResourceKind::DescriptorTableSlot)
+ {
+ return true;
+ }
+
+ if (context.objectLayoutOptions.hlslToVulkanKindFlags)
+ {
+ const auto hlslToVulkanKind = HLSLToVulkanLayoutOptions::getKind(kind);
+ // If it maps to a kind and it is enabled it is 'in effect' a Descriptor slot
+ return hlslToVulkanKind != HLSLToVulkanLayoutOptions::Kind::Invalid &&
+ (context.objectLayoutOptions.hlslToVulkanKindFlags & HLSLToVulkanLayoutOptions::getKindFlag(hlslToVulkanKind));
+ }
+
+ return false;
+}
+
static TypeLayoutResult createArrayLikeTypeLayout(
TypeLayoutContext const& context,
Type* type,
@@ -3472,6 +3546,13 @@ static TypeLayoutResult createArrayLikeTypeLayout(
LayoutSize arrayResourceCount = 0;
+ // We copy because if the element is *actually* DescriptorSlot like,
+ // we'll change the type.
+ // NOTE! That as it stands this will change the resource type from an HLSL type
+ // to Descriptor slot. This scenario happens when we have HLSLToVulkanLayoutOptions
+ // enabled, we layout with some HLSL types.
+ auto elementResourceKind = elementResourceInfo.kind;
+
// In almost all cases, the resources consumed by an array
// will be its element count times the resources consumed
// by its element type.
@@ -3480,14 +3561,15 @@ static TypeLayoutResult createArrayLikeTypeLayout(
// compiling to GLSL for Vulkan, where an entire array
// only consumes a single descriptor-table slot.
//
- if (elementResourceInfo.kind == LayoutResourceKind::DescriptorTableSlot)
+ if (_isDescriptorSlotLike(context, elementResourceKind))
{
arrayResourceCount = elementResourceInfo.count;
+ elementResourceKind = LayoutResourceKind::DescriptorTableSlot;
}
// The second exception to this is arrays of an existential type
// where the entire array should be specialized to a single concrete type.
//
- else if (elementResourceInfo.kind == LayoutResourceKind::ExistentialTypeParam)
+ else if (elementResourceKind == LayoutResourceKind::ExistentialTypeParam)
{
arrayResourceCount = elementResourceInfo.count;
}
@@ -3505,7 +3587,7 @@ static TypeLayoutResult createArrayLikeTypeLayout(
else if(
elementCount.isInfinite()
&& adjustedElementTypeLayout != elementTypeLayout
- && doesResourceRequireAdjustmentForArrayOfStructs(elementResourceInfo.kind) )
+ && doesResourceRequireAdjustmentForArrayOfStructs(elementResourceKind) )
{
// We want to ignore resource types consumed by the element type
// that need adjustement if the array size is infinite, since
@@ -3611,7 +3693,7 @@ static TypeLayoutResult _createTypeLayout(
// different from a `Texture2D<U>` in terms of how it
// should be handled as a member of a container.
//
- auto info = getParameterGroupLayoutInfo(parameterGroupType, rules);
+ auto info = _getParameterGroupLayoutInfo(context, parameterGroupType, rules);
// The more interesting case, though, is when the user
// is requesting us to actually create a `TypeLayout`,
@@ -3633,7 +3715,7 @@ static TypeLayoutResult _createTypeLayout(
else if (const auto samplerStateType = as<SamplerStateType>(type))
{
return createSimpleTypeLayout(
- rules->GetObjectLayout(ShaderParameterKind::SamplerState),
+ rules->GetObjectLayout(ShaderParameterKind::SamplerState, context.objectLayoutOptions),
type,
rules);
}
@@ -3654,7 +3736,7 @@ static TypeLayoutResult _createTypeLayout(
}
return createSimpleTypeLayout(
- rules->GetObjectLayout(kind),
+ rules->GetObjectLayout(kind, context.objectLayoutOptions),
type,
rules);
}
@@ -3675,7 +3757,7 @@ static TypeLayoutResult _createTypeLayout(
}
return createSimpleTypeLayout(
- rules->GetObjectLayout(kind),
+ rules->GetObjectLayout(kind, context.objectLayoutOptions),
type,
rules);
}
@@ -3696,7 +3778,7 @@ static TypeLayoutResult _createTypeLayout(
}
return createSimpleTypeLayout(
- rules->GetObjectLayout(kind),
+ rules->GetObjectLayout(kind, context.objectLayoutOptions),
type,
rules);
}
@@ -3704,7 +3786,7 @@ static TypeLayoutResult _createTypeLayout(
// TODO: need a better way to handle this stuff...
#define CASE(TYPE, KIND) \
else if(auto type_##TYPE = as<TYPE>(type)) do { \
- auto info = rules->GetObjectLayout(ShaderParameterKind::KIND); \
+ auto info = rules->GetObjectLayout(ShaderParameterKind::KIND, context.objectLayoutOptions); \
auto typeLayout = createStructuredBufferTypeLayout( \
context, \
ShaderParameterKind::KIND, \
@@ -3726,7 +3808,7 @@ static TypeLayoutResult _createTypeLayout(
#define CASE(TYPE, KIND) \
else if(as<TYPE>(type)) do { \
return createSimpleTypeLayout( \
- rules->GetObjectLayout(ShaderParameterKind::KIND), \
+ rules->GetObjectLayout(ShaderParameterKind::KIND, context.objectLayoutOptions), \
type, rules); \
} while(0)