Skip to content

Commit a29145e

Browse files
authored
[SPIR-V] Fix resource heap & fvk-bind-register interactions (microsoft#7858)
The interaction between `-fvk-bind-register` and the resource/sampler heaps were not tested, and broken. This commit solves this by requiring the `-fvk-bind-sampler-heap` or `-fvk-bind-resource-heap` flag to be used if the `-fvk-bind-register` flag is present and a resource/sampler heap is present. An alternative solution would be to allow implicit bindings on heaps while other resources require the register attribute, but I think it would be less useful as the goal of using this flag is to have full control over the bindings. This commit refactorizes a bit the helper functions isResourceHeap/isSamplerHeap, but this part is NFC. The main bit is in DeclResultIdMapper, where a special case is added the the heaps. Fixes microsoft#7857
1 parent f930c1d commit a29145e

8 files changed

Lines changed: 100 additions & 23 deletions

tools/clang/include/clang/SPIRV/AstTypeProbe.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,12 @@ bool isRWStructuredBuffer(QualType type);
222222
bool isRWAppendConsumeSBuffer(QualType type);
223223

224224
/// \brief Returns true if the given type is a ResourceDescriptorHeap.
225-
bool isResourceDescriptorHeap(QualType type);
225+
bool isResourceDescriptorHeap(QualType T);
226+
bool isResourceDescriptorHeap(const Decl *D);
226227

227228
/// \brief Returns true if the given type is a SamplerDescriptorHeap.
228-
bool isSamplerDescriptorHeap(QualType type);
229+
bool isSamplerDescriptorHeap(const Decl *D);
230+
bool isSamplerDescriptorHeap(QualType T);
229231

230232
/// \brief Returns true if the given type is the HLSL ByteAddressBufferType.
231233
bool isByteAddressBuffer(QualType type);

tools/clang/lib/SPIRV/AstTypeProbe.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -995,18 +995,24 @@ bool isRWAppendConsumeSBuffer(QualType type) {
995995
isAppendStructuredBuffer(type);
996996
}
997997

998-
bool isResourceDescriptorHeap(QualType type) {
999-
if (const auto *rt = type->getAs<RecordType>()) {
1000-
return rt->getDecl()->getName() == ".Resource";
1001-
}
1002-
return false;
998+
bool isResourceDescriptorHeap(const Decl *D) {
999+
const VarDecl *VD = dyn_cast<VarDecl>(D);
1000+
return VD && isResourceDescriptorHeap(VD->getType());
10031001
}
10041002

1005-
bool isSamplerDescriptorHeap(QualType type) {
1006-
if (const auto *rt = type->getAs<RecordType>()) {
1007-
return rt->getDecl()->getName() == ".Sampler";
1008-
}
1009-
return false;
1003+
bool isResourceDescriptorHeap(QualType T) {
1004+
const RecordType *RT = T->getAs<RecordType>();
1005+
return RT && RT->getDecl()->getName() == ".Resource";
1006+
}
1007+
1008+
bool isSamplerDescriptorHeap(const Decl *D) {
1009+
const VarDecl *VD = dyn_cast<VarDecl>(D);
1010+
return VD && isSamplerDescriptorHeap(VD->getType());
1011+
}
1012+
1013+
bool isSamplerDescriptorHeap(QualType T) {
1014+
const RecordType *RT = T->getAs<RecordType>();
1015+
return RT && RT->getDecl()->getName() == ".Sampler";
10101016
}
10111017

10121018
bool isAKindOfStructuredOrByteBuffer(QualType type) {

tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,8 +1850,7 @@ void DeclResultIdMapper::createCounterVar(
18501850
assert(declType->isIncompleteArrayType());
18511851
counterType = spvContext.getRuntimeArrayType(counterType, noArrayStride);
18521852
}
1853-
} else if (isResourceDescriptorHeap(decl->getType()) ||
1854-
isSamplerDescriptorHeap(decl->getType())) {
1853+
} else if (isResourceDescriptorHeap(decl) || isSamplerDescriptorHeap(decl)) {
18551854
counterType = spvContext.getRuntimeArrayType(counterType, noArrayStride);
18561855
}
18571856

@@ -2517,18 +2516,33 @@ bool DeclResultIdMapper::decorateResourceBindings() {
25172516

25182517
spvBuilder.decorateDSetBinding(var.getSpirvInstr(), globalsSetNo,
25192518
globalsBindNo);
2519+
} else if (var.isResourceDescriptorHeap()) {
2520+
if (!spirvOptions.resourceHeapBinding) {
2521+
emitError("-fvk-bind-resource-heap is required when using "
2522+
"-fvk-bind-register",
2523+
var.getSourceLocation());
2524+
return false;
2525+
}
2526+
} else if (var.isSamplerDescriptorHeap()) {
2527+
if (!spirvOptions.samplerHeapBinding) {
2528+
emitError("-fvk-bind-sampler-heap is required when using "
2529+
"-fvk-bind-register",
2530+
var.getSourceLocation());
2531+
return false;
2532+
}
25202533
} else {
25212534
emitError(
25222535
"-fvk-bind-register requires register annotations on all resources",
25232536
var.getSourceLocation());
25242537
return false;
25252538
}
25262539

2540+
BindingSet bindingSet;
2541+
decorateResourceHeapsBindings(bindingSet);
25272542
return true;
25282543
}
25292544

25302545
BindingSet bindingSet;
2531-
25322546
// If some bindings are reserved for heaps, mark those are used.
25332547
if (spirvOptions.resourceHeapBinding)
25342548
bindingSet.useBinding(spirvOptions.resourceHeapBinding->binding,
@@ -2669,8 +2683,8 @@ bool DeclResultIdMapper::decorateResourceBindings() {
26692683

26702684
if (var.getDeclaration()) {
26712685
const VarDecl *decl = dyn_cast<VarDecl>(var.getDeclaration());
2672-
if (decl && (isResourceDescriptorHeap(decl->getType()) ||
2673-
isSamplerDescriptorHeap(decl->getType())))
2686+
if (decl &&
2687+
(isResourceDescriptorHeap(decl) || isSamplerDescriptorHeap(decl)))
26742688
continue;
26752689
}
26762690

@@ -2755,8 +2769,8 @@ void DeclResultIdMapper::decorateResourceHeapsBindings(BindingSet &bindingSet) {
27552769
if (!decl)
27562770
continue;
27572771

2758-
const bool isResourceHeap = isResourceDescriptorHeap(decl->getType());
2759-
const bool isSamplerHeap = isSamplerDescriptorHeap(decl->getType());
2772+
const bool isResourceHeap = isResourceDescriptorHeap(decl);
2773+
const bool isSamplerHeap = isSamplerDescriptorHeap(decl);
27602774

27612775
assert(!(var.isCounter() && isSamplerHeap));
27622776

@@ -2791,8 +2805,8 @@ void DeclResultIdMapper::decorateResourceHeapsBindings(BindingSet &bindingSet) {
27912805
if (!decl)
27922806
continue;
27932807

2794-
const bool isResourceHeap = isResourceDescriptorHeap(decl->getType());
2795-
const bool isSamplerHeap = isSamplerDescriptorHeap(decl->getType());
2808+
const bool isResourceHeap = isResourceDescriptorHeap(decl);
2809+
const bool isSamplerHeap = isSamplerDescriptorHeap(decl);
27962810
if (!isSamplerHeap && !isResourceHeap)
27972811
continue;
27982812
const SpirvCodeGenOptions::BindingInfo &info =

tools/clang/lib/SPIRV/DeclResultIdMapper.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "dxc/Support/SPIRVOptions.h"
1717
#include "spirv/unified1/spirv.hpp11"
1818
#include "clang/AST/Attr.h"
19+
#include "clang/SPIRV/AstTypeProbe.h"
1920
#include "clang/SPIRV/FeatureManager.h"
2021
#include "clang/SPIRV/SpirvBuilder.h"
2122
#include "llvm/ADT/ArrayRef.h"
@@ -33,7 +34,7 @@ class SpirvEmitter;
3334

3435
class ResourceVar {
3536
public:
36-
ResourceVar(SpirvVariable *var, const Decl *decl, SourceLocation loc,
37+
ResourceVar(SpirvVariable *var, const NamedDecl *decl, SourceLocation loc,
3738
const hlsl::RegisterAssignment *r, const VKBindingAttr *b,
3839
const VKCounterBindingAttr *cb, bool counter = false,
3940
bool globalsBuffer = false)
@@ -52,9 +53,17 @@ class ResourceVar {
5253
return counterBinding;
5354
}
5455

56+
bool isResourceDescriptorHeap() const {
57+
return spirv::isResourceDescriptorHeap(declaration);
58+
}
59+
60+
bool isSamplerDescriptorHeap() const {
61+
return spirv::isSamplerDescriptorHeap(declaration);
62+
}
63+
5564
private:
5665
SpirvVariable *variable; ///< The variable
57-
const Decl *declaration; ///< The declaration
66+
const NamedDecl *declaration; ///< The declaration
5867
SourceLocation srcLoc; ///< Source location
5968
const hlsl::RegisterAssignment *reg; ///< HLSL register assignment
6069
const VKBindingAttr *binding; ///< Vulkan binding assignment
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %dxc -T ps_6_8 -E main -fvk-bind-register s10 0 1 2 -fcgl -fvk-bind-resource-heap 3 4 %s -spirv | FileCheck %s
2+
3+
// CHECK: OpDecorate %Sampler DescriptorSet 2
4+
// CHECK: OpDecorate %Sampler Binding 1
5+
SamplerState Sampler : register(s10);
6+
7+
// CHECK: OpDecorate %ResourceDescriptorHeap DescriptorSet 4
8+
// CHECK: OpDecorate %ResourceDescriptorHeap Binding 3
9+
10+
float4 main() : SV_Target {
11+
Texture2D Texture = ResourceDescriptorHeap[0];
12+
return Texture.Sample(Sampler, float2(0.1, 0.2));
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: not %dxc -T ps_6_8 -E main -fvk-bind-register s10 0 10 0 -fcgl %s -spirv 2>&1 | FileCheck %s
2+
3+
SamplerState Sampler : register(s10);
4+
5+
float4 main() : SV_Target {
6+
Texture2D Texture = ResourceDescriptorHeap[0];
7+
return Texture.Sample(Sampler, float2(0.1, 0.2));
8+
}
9+
10+
// CHECK: error: -fvk-bind-resource-heap is required when using -fvk-bind-register
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: not %dxc -T ps_6_8 -E main -fvk-bind-register s10 0 10 0 -fcgl %s -spirv 2>&1 | FileCheck %s
2+
3+
Texture2D Texture : register(s10);
4+
5+
float4 main() : SV_Target {
6+
SamplerState Sampler = SamplerDescriptorHeap[0];
7+
return Texture.Sample(Sampler, float2(0.1, 0.2));
8+
}
9+
10+
// CHECK: error: -fvk-bind-sampler-heap is required when using -fvk-bind-register
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %dxc -T ps_6_8 -E main -fvk-bind-register s10 0 1 2 -fcgl -fvk-bind-sampler-heap 3 4 %s -spirv | FileCheck %s
2+
3+
// CHECK: OpDecorate %Texture DescriptorSet 2
4+
// CHECK: OpDecorate %Texture Binding 1
5+
Texture2D Texture : register(s10);
6+
7+
// CHECK: OpDecorate %SamplerDescriptorHeap DescriptorSet 4
8+
// CHECK: OpDecorate %SamplerDescriptorHeap Binding 3
9+
10+
float4 main() : SV_Target {
11+
SamplerState Sampler = SamplerDescriptorHeap[0];
12+
return Texture.Sample(Sampler, float2(0.1, 0.2));
13+
}

0 commit comments

Comments
 (0)