Skip to content

Commit 2983537

Browse files
committed
GetDimensions
1 parent 1133da2 commit 2983537

File tree

3 files changed

+211
-3
lines changed

3 files changed

+211
-3
lines changed

tools/clang/lib/AST/ASTContextHLSL.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,8 @@ CXXRecordDecl *hlsl::DeclareVkSampledTexture2DType(ASTContext &context,
13881388

13891389
QualType floatType = context.FloatTy;
13901390
QualType uintType = context.UnsignedIntTy;
1391+
QualType intType = context.IntTy;
1392+
13911393
// Add Sample method
13921394
// Sample(location)
13931395
CXXMethodDecl *sampleDecl = CreateObjectFunctionDeclarationWithParams(
@@ -1489,6 +1491,101 @@ CXXRecordDecl *hlsl::DeclareVkSampledTexture2DType(ASTContext &context,
14891491
context, "op", "", static_cast<int>(hlsl::IntrinsicOp::MOP_Gather)));
14901492
gatherDecl3->addAttr(HLSLCXXOverloadAttr::CreateImplicit(context));
14911493

1494+
// GetDimensions(width, height)
1495+
QualType getDimensionsParams2[] = {context.getLValueReferenceType(uintType),
1496+
context.getLValueReferenceType(uintType)};
1497+
StringRef getDimensionsNames2[] = {"width", "height"};
1498+
CXXMethodDecl *getDimensionsDecl2 = CreateObjectFunctionDeclarationWithParams(
1499+
context, recordDecl, context.VoidTy, getDimensionsParams2,
1500+
getDimensionsNames2,
1501+
context.DeclarationNames.getIdentifier(
1502+
&context.Idents.get("GetDimensions")),
1503+
/*isConst*/ true);
1504+
getDimensionsDecl2->addAttr(HLSLIntrinsicAttr::CreateImplicit(
1505+
context, "op", "",
1506+
static_cast<int>(hlsl::IntrinsicOp::MOP_GetDimensions)));
1507+
// GetDimensions(width, height) float version
1508+
QualType getDimensionsParams2Float[] = {
1509+
context.getLValueReferenceType(floatType),
1510+
context.getLValueReferenceType(floatType)};
1511+
StringRef getDimensionsNames2Float[] = {"width", "height"};
1512+
CXXMethodDecl *getDimensionsDecl2Float =
1513+
CreateObjectFunctionDeclarationWithParams(
1514+
context, recordDecl, context.VoidTy, getDimensionsParams2Float,
1515+
getDimensionsNames2Float,
1516+
context.DeclarationNames.getIdentifier(
1517+
&context.Idents.get("GetDimensions")),
1518+
/*isConst*/ true);
1519+
getDimensionsDecl2Float->addAttr(HLSLIntrinsicAttr::CreateImplicit(
1520+
context, "op", "",
1521+
static_cast<int>(hlsl::IntrinsicOp::MOP_GetDimensions)));
1522+
// GetDimensions(width, height) int version
1523+
QualType getDimensionsParams2Int[] = {
1524+
context.getLValueReferenceType(intType),
1525+
context.getLValueReferenceType(intType)};
1526+
StringRef getDimensionsNames2Int[] = {"width", "height"};
1527+
CXXMethodDecl *getDimensionsDecl2Int =
1528+
CreateObjectFunctionDeclarationWithParams(
1529+
context, recordDecl, context.VoidTy, getDimensionsParams2Int,
1530+
getDimensionsNames2Int,
1531+
context.DeclarationNames.getIdentifier(
1532+
&context.Idents.get("GetDimensions")),
1533+
/*isConst*/ true);
1534+
getDimensionsDecl2Int->addAttr(HLSLIntrinsicAttr::CreateImplicit(
1535+
context, "op", "",
1536+
static_cast<int>(hlsl::IntrinsicOp::MOP_GetDimensions)));
1537+
1538+
// GetDimensions(mipLevel, width, height, numLevels)
1539+
QualType getDimensionsParams4[] = {uintType,
1540+
context.getLValueReferenceType(uintType),
1541+
context.getLValueReferenceType(uintType),
1542+
context.getLValueReferenceType(uintType)};
1543+
StringRef getDimensionsNames4[] = {"mipLevel", "width", "height",
1544+
"numLevels"};
1545+
CXXMethodDecl *getDimensionsDecl4 = CreateObjectFunctionDeclarationWithParams(
1546+
context, recordDecl, context.VoidTy, getDimensionsParams4,
1547+
getDimensionsNames4,
1548+
context.DeclarationNames.getIdentifier(
1549+
&context.Idents.get("GetDimensions")),
1550+
/*isConst*/ true);
1551+
getDimensionsDecl4->addAttr(HLSLIntrinsicAttr::CreateImplicit(
1552+
context, "op", "",
1553+
static_cast<int>(hlsl::IntrinsicOp::MOP_GetDimensions)));
1554+
// GetDimensions(mipLevel, width, height, numLevels) float version
1555+
QualType getDimensionsParams4Float[] = {
1556+
uintType, context.getLValueReferenceType(floatType),
1557+
context.getLValueReferenceType(floatType),
1558+
context.getLValueReferenceType(floatType)};
1559+
StringRef getDimensionsNames4Float[] = {"mipLevel", "width", "height",
1560+
"numLevels"};
1561+
CXXMethodDecl *getDimensionsDecl4Float =
1562+
CreateObjectFunctionDeclarationWithParams(
1563+
context, recordDecl, context.VoidTy, getDimensionsParams4Float,
1564+
getDimensionsNames4Float,
1565+
context.DeclarationNames.getIdentifier(
1566+
&context.Idents.get("GetDimensions")),
1567+
/*isConst*/ true);
1568+
getDimensionsDecl4Float->addAttr(HLSLIntrinsicAttr::CreateImplicit(
1569+
context, "op", "",
1570+
static_cast<int>(hlsl::IntrinsicOp::MOP_GetDimensions)));
1571+
// GetDimensions(mipLevel, width, height, numLevels) int version
1572+
QualType getDimensionsParams4Int[] = {
1573+
uintType, context.getLValueReferenceType(intType),
1574+
context.getLValueReferenceType(intType),
1575+
context.getLValueReferenceType(intType)};
1576+
StringRef getDimensionsNames4Int[] = {"mipLevel", "width", "height",
1577+
"numLevels"};
1578+
CXXMethodDecl *getDimensionsDecl4Int =
1579+
CreateObjectFunctionDeclarationWithParams(
1580+
context, recordDecl, context.VoidTy, getDimensionsParams4Int,
1581+
getDimensionsNames4Int,
1582+
context.DeclarationNames.getIdentifier(
1583+
&context.Idents.get("GetDimensions")),
1584+
/*isConst*/ true);
1585+
getDimensionsDecl4Int->addAttr(HLSLIntrinsicAttr::CreateImplicit(
1586+
context, "op", "",
1587+
static_cast<int>(hlsl::IntrinsicOp::MOP_GetDimensions)));
1588+
14921589
Builder.completeDefinition();
14931590
return recordDecl;
14941591
}

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "llvm/ADT/SetVector.h"
3333
#include "llvm/ADT/StringExtras.h"
3434
#include "llvm/Support/Casting.h"
35+
#include "llvm/Support/raw_ostream.h"
3536

3637
#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
3738
#include "clang/Basic/Version.h"
@@ -4306,7 +4307,18 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
43064307
const Expr *mipLevel = nullptr, *numLevels = nullptr, *numSamples = nullptr;
43074308

43084309
assert(isTexture(type) || isRWTexture(type) || isBuffer(type) ||
4309-
isRWBuffer(type));
4310+
isRWBuffer(type) || isSampledTexture(type));
4311+
if (isSampledTexture(type)) {
4312+
LowerTypeVisitor lowerTypeVisitor(astContext, spvContext, spirvOptions,
4313+
spvBuilder);
4314+
const SpirvType *spvType = lowerTypeVisitor.lowerType(
4315+
type, SpirvLayoutRule::Void, llvm::None, expr->getExprLoc());
4316+
// Get image type based on type, assuming type is a sampledimage type
4317+
const auto *sampledType = cast<SampledImageType>(spvType);
4318+
const SpirvType *imgType = sampledType->getImageType();
4319+
objectInstr = spvBuilder.createUnaryOp(spv::Op::OpImage, imgType,
4320+
objectInstr, expr->getExprLoc());
4321+
}
43104322

43114323
// For Texture1D, arguments are either:
43124324
// a) width
@@ -4340,6 +4352,9 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
43404352
// a) width, height, elements
43414353
// b) MipLevel, width, height, elements, NumLevels
43424354

4355+
// SampledTexture types follow the same rules above, as
4356+
// this method doesn't require a Sampler argument.
4357+
43434358
// Note: SPIR-V Spec requires return type of OpImageQuerySize(Lod) to be a
43444359
// scalar/vector of integers. SPIR-V Spec also requires return type of
43454360
// OpImageQueryLevels and OpImageQuerySamples to be scalar integers.
@@ -4357,6 +4372,7 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
43574372

43584373
if ((typeName == "Texture1D" && numArgs > 1) ||
43594374
(typeName == "Texture2D" && numArgs > 2) ||
4375+
(typeName == "SampledTexture2D" && numArgs > 2) ||
43604376
(typeName == "TextureCube" && numArgs > 2) ||
43614377
(typeName == "Texture3D" && numArgs > 3) ||
43624378
(typeName == "Texture1DArray" && numArgs > 2) ||
@@ -4395,7 +4411,7 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
43954411
// Only Texture types use ImageQuerySizeLod.
43964412
// TextureMS, RWTexture, Buffers, RWBuffers use ImageQuerySize.
43974413
SpirvInstruction *lod = nullptr;
4398-
if (isTexture(type) && !numSamples) {
4414+
if ((isTexture(type) || isSampledTexture(type)) && !numSamples) {
43994415
if (mipLevel) {
44004416
// For Texture types when mipLevel argument is present.
44014417
lod = doExpr(mipLevel, range);
@@ -6442,7 +6458,8 @@ SpirvInstruction *
64426458
SpirvEmitter::processGetDimensions(const CXXMemberCallExpr *expr) {
64436459
const auto objectType = expr->getImplicitObjectArgument()->getType();
64446460
if (isTexture(objectType) || isRWTexture(objectType) ||
6445-
isBuffer(objectType) || isRWBuffer(objectType)) {
6461+
isBuffer(objectType) || isRWBuffer(objectType) ||
6462+
isSampledTexture(objectType)) {
64466463
return processBufferTextureGetDimensions(expr);
64476464
} else if (isByteAddressBuffer(objectType) ||
64486465
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+
}

0 commit comments

Comments
 (0)