Skip to content

Commit 5534b0d

Browse files
authored
Rework type layout for ExistentialSpecializedType (shader-slang#1531)
1 parent 44929d9 commit 5534b0d

File tree

2 files changed

+108
-20
lines changed

2 files changed

+108
-20
lines changed

source/slang/slang-type-layout.cpp

+90-20
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ struct HLSLRayTracingLayoutRulesImpl : DefaultVaryingLayoutRulesImpl
687687
{}
688688
};
689689

690+
DefaultLayoutRulesImpl kDefaultLayoutRulesImpl;
690691
Std140LayoutRulesImpl kStd140LayoutRulesImpl;
691692
Std430LayoutRulesImpl kStd430LayoutRulesImpl;
692693
HLSLConstantBufferLayoutRulesImpl kHLSLConstantBufferLayoutRulesImpl;
@@ -710,6 +711,7 @@ HLSLRayTracingLayoutRulesImpl kHLSLHitAttributesParameterLayoutRulesImpl(LayoutR
710711

711712
struct GLSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl
712713
{
714+
virtual LayoutRulesImpl* getAnyValueRules() override;
713715
virtual LayoutRulesImpl* getConstantBufferRules() override;
714716
virtual LayoutRulesImpl* getPushConstantBufferRules() override;
715717
virtual LayoutRulesImpl* getTextureBufferRules() override;
@@ -730,6 +732,7 @@ struct GLSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl
730732

731733
struct HLSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl
732734
{
735+
virtual LayoutRulesImpl* getAnyValueRules() override;
733736
virtual LayoutRulesImpl* getConstantBufferRules() override;
734737
virtual LayoutRulesImpl* getPushConstantBufferRules() override;
735738
virtual LayoutRulesImpl* getTextureBufferRules() override;
@@ -750,6 +753,7 @@ struct HLSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl
750753

751754
struct CPULayoutRulesFamilyImpl : LayoutRulesFamilyImpl
752755
{
756+
virtual LayoutRulesImpl* getAnyValueRules() override;
753757
virtual LayoutRulesImpl* getConstantBufferRules() override;
754758
virtual LayoutRulesImpl* getPushConstantBufferRules() override;
755759
virtual LayoutRulesImpl* getTextureBufferRules() override;
@@ -769,6 +773,7 @@ struct CPULayoutRulesFamilyImpl : LayoutRulesFamilyImpl
769773

770774
struct CUDALayoutRulesFamilyImpl : LayoutRulesFamilyImpl
771775
{
776+
virtual LayoutRulesImpl* getAnyValueRules() override;
772777
virtual LayoutRulesImpl* getConstantBufferRules() override;
773778
virtual LayoutRulesImpl* getPushConstantBufferRules() override;
774779
virtual LayoutRulesImpl* getTextureBufferRules() override;
@@ -903,6 +908,12 @@ LayoutRulesImpl kCPULayoutRulesImpl_ = {
903908
&kCPULayoutRulesFamilyImpl, &kCPULayoutRulesImpl, &kCPUObjectLayoutRulesImpl,
904909
};
905910

911+
LayoutRulesImpl kCPUAnyValueLayoutRulesImpl_ = {
912+
&kCPULayoutRulesFamilyImpl,
913+
&kDefaultLayoutRulesImpl,
914+
&kCPUObjectLayoutRulesImpl,
915+
};
916+
906917
// CUDA
907918

908919
static CUDAObjectLayoutRulesImpl kCUDAObjectLayoutRulesImpl;
@@ -912,6 +923,11 @@ LayoutRulesImpl kCUDALayoutRulesImpl_ = {
912923
&kCUDALayoutRulesFamilyImpl, &kCUDALayoutRulesImpl, &kCUDAObjectLayoutRulesImpl,
913924
};
914925

926+
LayoutRulesImpl kCUDAAnyValueLayoutRulesImpl_ = {
927+
&kCUDALayoutRulesFamilyImpl,
928+
&kDefaultLayoutRulesImpl,
929+
&kCUDAObjectLayoutRulesImpl,
930+
};
915931

916932
// GLSL cases
917933

@@ -923,6 +939,12 @@ LayoutRulesImpl kStd430LayoutRulesImpl_ = {
923939
&kGLSLLayoutRulesFamilyImpl, &kStd430LayoutRulesImpl, &kGLSLObjectLayoutRulesImpl,
924940
};
925941

942+
LayoutRulesImpl kGLSLAnyValueLayoutRulesImpl_ = {
943+
&kGLSLLayoutRulesFamilyImpl,
944+
&kDefaultLayoutRulesImpl,
945+
&kGLSLPushConstantBufferObjectLayoutRulesImpl_,
946+
};
947+
926948
LayoutRulesImpl kGLSLPushConstantLayoutRulesImpl_ = {
927949
&kGLSLLayoutRulesFamilyImpl, &kStd430LayoutRulesImpl, &kGLSLPushConstantBufferObjectLayoutRulesImpl_,
928950
};
@@ -962,6 +984,12 @@ LayoutRulesImpl kGLSLStructuredBufferLayoutRulesImpl_ = {
962984

963985
// HLSL cases
964986

987+
LayoutRulesImpl kHLSLAnyValueLayoutRulesImpl_ = {
988+
&kHLSLLayoutRulesFamilyImpl,
989+
&kDefaultLayoutRulesImpl,
990+
&kHLSLObjectLayoutRulesImpl,
991+
};
992+
965993
LayoutRulesImpl kHLSLConstantBufferLayoutRulesImpl_ = {
966994
&kHLSLLayoutRulesFamilyImpl, &kHLSLConstantBufferLayoutRulesImpl, &kHLSLObjectLayoutRulesImpl,
967995
};
@@ -992,6 +1020,11 @@ LayoutRulesImpl kHLSLHitAttributesParameterLayoutRulesImpl_ = {
9921020

9931021
// GLSL Family
9941022

1023+
LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getAnyValueRules()
1024+
{
1025+
return &kGLSLAnyValueLayoutRulesImpl_;
1026+
}
1027+
9951028
LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getConstantBufferRules()
9961029
{
9971030
return &kStd140LayoutRulesImpl_;
@@ -1060,6 +1093,11 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getStructuredBufferRules()
10601093

10611094
// HLSL Family
10621095

1096+
LayoutRulesImpl* HLSLLayoutRulesFamilyImpl::getAnyValueRules()
1097+
{
1098+
return &kHLSLAnyValueLayoutRulesImpl_;
1099+
}
1100+
10631101
LayoutRulesImpl* HLSLLayoutRulesFamilyImpl::getConstantBufferRules()
10641102
{
10651103
return &kHLSLConstantBufferLayoutRulesImpl_;
@@ -1129,6 +1167,11 @@ LayoutRulesImpl* HLSLLayoutRulesFamilyImpl::getHitAttributesParameterRules()
11291167

11301168
// CPU Family
11311169

1170+
LayoutRulesImpl* CPULayoutRulesFamilyImpl::getAnyValueRules()
1171+
{
1172+
return &kCPUAnyValueLayoutRulesImpl_;
1173+
}
1174+
11321175
LayoutRulesImpl* CPULayoutRulesFamilyImpl::getConstantBufferRules()
11331176
{
11341177
return &kCPULayoutRulesImpl_;
@@ -1190,6 +1233,11 @@ LayoutRulesImpl* CPULayoutRulesFamilyImpl::getStructuredBufferRules()
11901233

11911234
// CUDA Family
11921235

1236+
LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getAnyValueRules()
1237+
{
1238+
return &kCUDAAnyValueLayoutRulesImpl_;
1239+
}
1240+
11931241
LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getConstantBufferRules()
11941242
{
11951243
return &kCUDALayoutRulesImpl_;
@@ -3613,43 +3661,65 @@ static TypeLayoutResult _createTypeLayout(
36133661
typeLayout->type = type;
36143662
typeLayout->rules = rules;
36153663

3616-
if (isCPUTarget(context.targetReq) || isCUDATarget(context.targetReq))
3664+
LayoutSize fixedExistentialValueSize = 0;
3665+
bool useFixedSizedExistentialValue =
3666+
isCPUTarget(context.targetReq) || isCUDATarget(context.targetReq);
3667+
if (useFixedSizedExistentialValue)
36173668
{
3618-
LayoutSize fixedSize = 16;
3669+
fixedExistentialValueSize = 16;
36193670
if (auto anyValueAttr =
36203671
interfaceDeclRef.getDecl()->findModifier<AnyValueSizeAttribute>())
36213672
{
3622-
fixedSize += anyValueAttr->size;
3673+
fixedExistentialValueSize = anyValueAttr->size;
36233674
}
3624-
else
3625-
{
3626-
// The interface type does not have an `[anyValueSize]` attribute,
3627-
// assume a default of 8 bytes.
3628-
fixedSize += 8;
3629-
}
3630-
typeLayout->addResourceUsage(LayoutResourceKind::Uniform, fixedSize);
3675+
typeLayout->addResourceUsage(LayoutResourceKind::Uniform, fixedExistentialValueSize + 16);
36313676
}
36323677
typeLayout->addResourceUsage(LayoutResourceKind::ExistentialTypeParam, 1);
36333678
typeLayout->addResourceUsage(LayoutResourceKind::ExistentialObjectParam, 1);
36343679

36353680
// If there are any concrete types available, the first one will be
36363681
// the value that should be plugged into the slot we just introduced.
36373682
//
3638-
if( context.specializationArgCount )
3683+
if (context.specializationArgCount)
36393684
{
36403685
auto& specializationArg = context.specializationArgs[0];
36413686
Type* concreteType = as<Type>(specializationArg.val);
36423687
SLANG_ASSERT(concreteType);
36433688

3644-
RefPtr<TypeLayout> concreteTypeLayout = createTypeLayout(context, concreteType);
3645-
3646-
// Layout for this specialized interface type then results
3647-
// in a type layout that tracks both the resource usage of the
3648-
// interface type itself (just the type + value slots introduced
3649-
// above), plus a "pending data" type that represents the value
3650-
// conceptually pointed to by the interface-type field/variable at runtime.
3651-
//
3652-
typeLayout->pendingDataTypeLayout = concreteTypeLayout;
3689+
// Always use AnyValueRules regardless of the enclosing environment's layout rule
3690+
// for existential values.
3691+
auto anyValueRules = context.getRulesFamily()->getAnyValueRules();
3692+
3693+
// TODO: for traditional GPU targets (HLSL/GLSL) we don't force
3694+
// anyValueRule for now, since it requires additional work to load
3695+
// the existential value. We should remove this special case logic
3696+
// and always use anyValueRule once we implement the correct loading
3697+
// code gen logic for these targets.
3698+
if (!(isCPUTarget(context.targetReq) || isCUDATarget(context.targetReq)))
3699+
anyValueRules = context.rules;
3700+
3701+
RefPtr<TypeLayout> concreteTypeLayout =
3702+
createTypeLayout(context.with(anyValueRules), concreteType);
3703+
auto uniformLayoutInfo =
3704+
concreteTypeLayout->FindResourceInfo(LayoutResourceKind::Uniform);
3705+
if (!useFixedSizedExistentialValue ||
3706+
(uniformLayoutInfo && uniformLayoutInfo->count > fixedExistentialValueSize))
3707+
{
3708+
// TODO: for targets that supports pointers, oversized existential values
3709+
// should be placed in an overflow region and only a pointer is needed in
3710+
// the place of the fixed sized uniform slot.
3711+
// We only need the "pending layout" mechanism for targets that does not
3712+
// support pointers.
3713+
3714+
// For legacy targets without pointer support, the layout for this
3715+
// specialized interface type then results in a type layout that tracks
3716+
// both the resource usage of the interface type itself (just the
3717+
// type + value slots introduced above), plus a "pending data" type that
3718+
// represents the value conceptually pointed to by the interface-type
3719+
// field/variable at runtime.
3720+
//
3721+
typeLayout->pendingDataTypeLayout = concreteTypeLayout;
3722+
}
36533723
}
36543724

36553725
return TypeLayoutResult(typeLayout, SimpleLayoutInfo());

source/slang/slang-type-layout.h

+18
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,23 @@ struct LayoutSize
7373
return raw != that.raw;
7474
}
7575

76+
bool operator>(LayoutSize that) const
77+
{
78+
if (that.isFinite())
79+
{
80+
if (this->isFinite())
81+
return this->raw > that.raw;
82+
return true;
83+
84+
}
85+
else
86+
{
87+
if (that.isInfinite())
88+
return false;
89+
return true;
90+
}
91+
}
92+
7693
void operator+=(LayoutSize right)
7794
{
7895
if( isInfinite() ) {}
@@ -892,6 +909,7 @@ struct LayoutRulesImpl
892909

893910
struct LayoutRulesFamilyImpl
894911
{
912+
virtual LayoutRulesImpl* getAnyValueRules() = 0;
895913
virtual LayoutRulesImpl* getConstantBufferRules() = 0;
896914
virtual LayoutRulesImpl* getPushConstantBufferRules() = 0;
897915
virtual LayoutRulesImpl* getTextureBufferRules() = 0;

0 commit comments

Comments
 (0)