Skip to content

Commit bdaeae0

Browse files
authored
[SPIR-V][vk::SampledTexture] #3. Add .GetDimensions() methods for vk::SampledTexture2D type. (#8076)
Part of #7979 Implement methods for `vk::SampledTexture2D`: ```hlsl void GetDimensions(uint mipLevel, uint width, uint height, uint numLevels) ``` Please see the last commit
1 parent e6b4e88 commit bdaeae0

File tree

3 files changed

+117
-3
lines changed

3 files changed

+117
-3
lines changed

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4328,7 +4328,18 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
43284328
const Expr *mipLevel = nullptr, *numLevels = nullptr, *numSamples = nullptr;
43294329

43304330
assert(isTexture(type) || isRWTexture(type) || isBuffer(type) ||
4331-
isRWBuffer(type));
4331+
isRWBuffer(type) || isSampledTexture(type));
4332+
if (isSampledTexture(type)) {
4333+
LowerTypeVisitor lowerTypeVisitor(astContext, spvContext, spirvOptions,
4334+
spvBuilder);
4335+
const SpirvType *spvType = lowerTypeVisitor.lowerType(
4336+
type, SpirvLayoutRule::Void, llvm::None, expr->getExprLoc());
4337+
// Get image type based on type, assuming type is a sampledimage type
4338+
const auto *sampledType = cast<SampledImageType>(spvType);
4339+
const SpirvType *imgType = sampledType->getImageType();
4340+
objectInstr = spvBuilder.createUnaryOp(spv::Op::OpImage, imgType,
4341+
objectInstr, expr->getExprLoc());
4342+
}
43324343

43334344
// For Texture1D, arguments are either:
43344345
// a) width
@@ -4362,6 +4373,9 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
43624373
// a) width, height, elements
43634374
// b) MipLevel, width, height, elements, NumLevels
43644375

4376+
// SampledTexture types follow the same rules above, as
4377+
// this method doesn't require a Sampler argument.
4378+
43654379
// Note: SPIR-V Spec requires return type of OpImageQuerySize(Lod) to be a
43664380
// scalar/vector of integers. SPIR-V Spec also requires return type of
43674381
// OpImageQueryLevels and OpImageQuerySamples to be scalar integers.
@@ -4379,6 +4393,7 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
43794393

43804394
if ((typeName == "Texture1D" && numArgs > 1) ||
43814395
(typeName == "Texture2D" && numArgs > 2) ||
4396+
(typeName == "SampledTexture2D" && numArgs > 2) ||
43824397
(typeName == "TextureCube" && numArgs > 2) ||
43834398
(typeName == "Texture3D" && numArgs > 3) ||
43844399
(typeName == "Texture1DArray" && numArgs > 2) ||
@@ -4417,7 +4432,7 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
44174432
// Only Texture types use ImageQuerySizeLod.
44184433
// TextureMS, RWTexture, Buffers, RWBuffers use ImageQuerySize.
44194434
SpirvInstruction *lod = nullptr;
4420-
if (isTexture(type) && !numSamples) {
4435+
if ((isTexture(type) || isSampledTexture(type)) && !numSamples) {
44214436
if (mipLevel) {
44224437
// For Texture types when mipLevel argument is present.
44234438
lod = doExpr(mipLevel, range);
@@ -6433,7 +6448,8 @@ SpirvInstruction *
64336448
SpirvEmitter::processGetDimensions(const CXXMemberCallExpr *expr) {
64346449
const auto objectType = expr->getImplicitObjectArgument()->getType();
64356450
if (isTexture(objectType) || isRWTexture(objectType) ||
6436-
isBuffer(objectType) || isRWBuffer(objectType)) {
6451+
isBuffer(objectType) || isRWBuffer(objectType) ||
6452+
isSampledTexture(objectType)) {
64376453
return processBufferTextureGetDimensions(expr);
64386454
} else if (isByteAddressBuffer(objectType) ||
64396455
isRWByteAddressBuffer(objectType) ||
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// RUN: %dxc -T ps_6_0 -E main -fcgl %s -spirv | FileCheck %s
2+
// RUN: not %dxc -T ps_6_0 -E main -fcgl %s -spirv -DERROR 2>&1 | FileCheck %s --check-prefix=ERROR
3+
4+
// CHECK: OpCapability ImageQuery
5+
6+
vk::SampledTexture2D<float4> t1;
7+
8+
void main() {
9+
uint mipLevel = 1;
10+
uint width, height, numLevels;
11+
12+
// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
13+
// CHECK-NEXT: [[image1:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
14+
// CHECK-NEXT: [[query1:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image1]] %int_0
15+
// CHECK-NEXT: [[query1_0:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 0
16+
// CHECK-NEXT: OpStore %width [[query1_0]]
17+
// CHECK-NEXT: [[query1_1:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 1
18+
// CHECK-NEXT: OpStore %height [[query1_1]]
19+
t1.GetDimensions(width, height);
20+
21+
// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
22+
// CHECK-NEXT: [[image2:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
23+
// CHECK-NEXT: [[mip:%[0-9]+]] = OpLoad %uint %mipLevel
24+
// CHECK-NEXT: [[query2:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image2]] [[mip]]
25+
// CHECK-NEXT: [[query2_0:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 0
26+
// CHECK-NEXT: OpStore %width [[query2_0]]
27+
// CHECK-NEXT: [[query2_1:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 1
28+
// CHECK-NEXT: OpStore %height [[query2_1]]
29+
// CHECK-NEXT: [[query_level_2:%[0-9]+]] = OpImageQueryLevels %uint [[image2]]
30+
// CHECK-NEXT: OpStore %numLevels [[query_level_2]]
31+
t1.GetDimensions(mipLevel, width, height, numLevels);
32+
33+
float f_width, f_height, f_numLevels;
34+
// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
35+
// CHECK-NEXT: [[image1:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
36+
// CHECK-NEXT: [[query1:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image1]] %int_0
37+
// CHECK-NEXT: [[query1_0:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 0
38+
// CHECK-NEXT: [[f_query1_0:%[0-9]+]] = OpConvertUToF %float [[query1_0]]
39+
// CHECK-NEXT: OpStore %f_width [[f_query1_0]]
40+
// CHECK-NEXT: [[query1_1:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 1
41+
// CHECK-NEXT: [[f_query1_1:%[0-9]+]] = OpConvertUToF %float [[query1_1]]
42+
// CHECK-NEXT: OpStore %f_height [[f_query1_1]]
43+
t1.GetDimensions(f_width, f_height);
44+
45+
// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
46+
// CHECK-NEXT: [[image2:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
47+
// CHECK-NEXT: [[mip:%[0-9]+]] = OpLoad %uint %mipLevel
48+
// CHECK-NEXT: [[query2:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image2]] [[mip]]
49+
// CHECK-NEXT: [[query2_0:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 0
50+
// CHECK-NEXT: [[f_query2_0:%[0-9]+]] = OpConvertUToF %float [[query2_0]]
51+
// CHECK-NEXT: OpStore %f_width [[f_query2_0]]
52+
// CHECK-NEXT: [[query2_1:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 1
53+
// CHECK-NEXT: [[f_query2_1:%[0-9]+]] = OpConvertUToF %float [[query2_1]]
54+
// CHECK-NEXT: OpStore %f_height [[f_query2_1]]
55+
// CHECK-NEXT: [[query_level_2:%[0-9]+]] = OpImageQueryLevels %uint [[image2]]
56+
// CHECK-NEXT: [[f_query_level_2:%[0-9]+]] = OpConvertUToF %float [[query_level_2]]
57+
// CHECK-NEXT: OpStore %f_numLevels [[f_query_level_2]]
58+
t1.GetDimensions(mipLevel, f_width, f_height, f_numLevels);
59+
60+
int i_width, i_height, i_numLevels;
61+
// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
62+
// CHECK-NEXT: [[image1:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
63+
// CHECK-NEXT: [[query1:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image1]] %int_0
64+
// CHECK-NEXT: [[query1_0:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 0
65+
// CHECK-NEXT: [[query_0_int:%[0-9]+]] = OpBitcast %int [[query1_0]]
66+
// CHECK-NEXT: OpStore %i_width [[query_0_int]]
67+
// CHECK-NEXT: [[query1_1:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 1
68+
// CHECK-NEXT: [[query_1_int:%[0-9]+]] = OpBitcast %int [[query1_1]]
69+
// CHECK-NEXT: OpStore %i_height [[query_1_int]]
70+
t1.GetDimensions(i_width, i_height);
71+
72+
// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
73+
// CHECK-NEXT: [[image2:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
74+
// CHECK-NEXT: [[mip:%[0-9]+]] = OpLoad %uint %mipLevel
75+
// CHECK-NEXT: [[query2:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image2]] [[mip]]
76+
// CHECK-NEXT: [[query2_0:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 0
77+
// CHECK-NEXT: [[query_0_int:%[0-9]+]] = OpBitcast %int [[query2_0]]
78+
// CHECK-NEXT: OpStore %i_width [[query_0_int]]
79+
// CHECK-NEXT: [[query2_1:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 1
80+
// CHECK-NEXT: [[query_1_int:%[0-9]+]] = OpBitcast %int [[query2_1]]
81+
// CHECK-NEXT: OpStore %i_height [[query_1_int]]
82+
// CHECK-NEXT: [[query_level_2:%[0-9]+]] = OpImageQueryLevels %uint [[image2]]
83+
// CHECK-NEXT: [[query_level_2_int:%[0-9]+]] = OpBitcast %int [[query_level_2]]
84+
// CHECK-NEXT: OpStore %i_numLevels [[query_level_2_int]]
85+
t1.GetDimensions(mipLevel, i_width, i_height, i_numLevels);
86+
87+
#ifdef ERROR
88+
// ERROR: error: Output argument must be an l-value
89+
t1.GetDimensions(mipLevel, 0, height, numLevels);
90+
91+
// ERROR: error: Output argument must be an l-value
92+
t1.GetDimensions(width, 20);
93+
#endif
94+
}

utils/hct/gen_intrin_main.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,4 +1243,8 @@ namespace VkSampledTexture2DMethods {
12431243
$match<0, -1> void<4> [[ro]] Gather(in float<2> x) : tex2d_t_gather;
12441244
$match<0, -1> void<4> [[ro]] Gather(in float<2> x, in int<2> o) : tex2d_t_gather_o;
12451245
$match<0, -1> void<4> [[]] Gather(in float<2> x, in int<2> o, out uint_only status) : tex2d_t_gather_o_s;
1246+
void [[]] GetDimensions(in uint x, out uint_only width, out $type2 height, out $type2 levels) : resinfo_uint;
1247+
void [[]] GetDimensions(in uint x, out float_like width, out $type2 height, out $type2 levels) : resinfo;
1248+
void [[]] GetDimensions(out uint_only width, out $type1 height) : resinfo_uint_o;
1249+
void [[]] GetDimensions(out float_like width, out $type1 height) : resinfo_o;
12461250
} namespace

0 commit comments

Comments
 (0)