[clang] 829440b - [HLSL] Implement Texture2DArray for HLSL (#203951)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 29 06:53:38 PDT 2026
Author: Tim Corringham
Date: 2026-06-29T14:53:29+01:00
New Revision: 829440b9e63eb3127e2af595aa45fa4b28b7a49a
URL: https://github.com/llvm/llvm-project/commit/829440b9e63eb3127e2af595aa45fa4b28b7a49a
DIFF: https://github.com/llvm/llvm-project/commit/829440b9e63eb3127e2af595aa45fa4b28b7a49a.diff
LOG: [HLSL] Implement Texture2DArray for HLSL (#203951)
Add support for the Texture2DArray type, builtin argument checking,
codegen, and associated tests.
This change also implements the parts of #194910 which could not be
tested without a HLSL texture array type.
Assisted by Cursor
Fixes #194944
---------
Co-authored-by: Tim Corringham <tcorring at amd.com>
Added:
clang/test/AST/HLSL/Texture2DArray-scalar-AST.hlsl
clang/test/AST/HLSL/Texture2DArray-shorthand-AST.hlsl
clang/test/AST/HLSL/Texture2DArray-vector-AST.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-CalculateLevelOfDetail.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-Gather.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-GetDimensions.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-Load.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-Mips.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-Sample.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-SampleBias.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-SampleCmp.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-SampleCmpLevelZero.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-SampleGrad.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-SampleLevel.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-Subscript.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-default-explicit-binding.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-default.hlsl
clang/test/CodeGenHLSL/resources/Texture2DArray-shorthand-contexts.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-CalculateLevelOfDetail.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-GetDimensions.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-SampleBias.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-SampleCmp.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-SampleCmpLevelZero.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-SampleGrad.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-SampleLevel.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-Sema.hlsl
clang/test/SemaHLSL/Resources/Texture2DArray-Subscript.hlsl
clang/test/SemaHLSL/Texture2DArray-Gather.hlsl
clang/test/SemaHLSL/Texture2DArray-GatherCmp-Vulkan.hlsl
clang/test/SemaHLSL/Texture2DArray-Load-errors.hlsl
clang/test/SemaHLSL/Texture2DArray-mips-errors.hlsl
llvm/test/CodeGen/DirectX/Texture2DArray-SampleBias.ll
llvm/test/CodeGen/DirectX/Texture2DArray-SampleGrad.ll
llvm/test/CodeGen/DirectX/Texture2DArray-annotateHandle.ll
llvm/test/CodeGen/SPIRV/hlsl-resources/Gather2DArray.ll
llvm/test/CodeGen/SPIRV/hlsl-resources/LoadLevel2DArray.ll
llvm/test/CodeGen/SPIRV/hlsl-resources/Sample2DArray.ll
llvm/test/CodeGen/SPIRV/hlsl-resources/SampleGrad2DArray.ll
Modified:
clang/lib/CodeGen/Targets/DirectX.cpp
clang/lib/CodeGen/Targets/SPIR.cpp
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
clang/lib/Sema/HLSLExternalSemaSource.cpp
clang/lib/Sema/SemaHLSL.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/Targets/DirectX.cpp b/clang/lib/CodeGen/Targets/DirectX.cpp
index e5b01c21e9e2f..f483a7b867016 100644
--- a/clang/lib/CodeGen/Targets/DirectX.cpp
+++ b/clang/lib/CodeGen/Targets/DirectX.cpp
@@ -97,7 +97,10 @@ llvm::Type *DirectXTargetCodeGenInfo::getHLSLType(
RK = llvm::dxil::ResourceKind::Texture1D;
break;
case llvm::dxil::ResourceDimension::Dim2D:
- RK = llvm::dxil::ResourceKind::Texture2D;
+ if (ResAttrs.IsArray)
+ RK = llvm::dxil::ResourceKind::Texture2DArray;
+ else
+ RK = llvm::dxil::ResourceKind::Texture2D;
break;
case llvm::dxil::ResourceDimension::Dim3D:
RK = llvm::dxil::ResourceKind::Texture3D;
@@ -106,7 +109,7 @@ llvm::Type *DirectXTargetCodeGenInfo::getHLSLType(
RK = llvm::dxil::ResourceKind::TextureCube;
break;
default:
- llvm_unreachable("Unsupported resource dimension for textur.");
+ llvm_unreachable("Unsupported resource dimension for texture.");
}
Ints.push_back(static_cast<unsigned>(RK));
}
diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp
index 0a96d612c8a87..88e7c7f9482a4 100644
--- a/clang/lib/CodeGen/Targets/SPIR.cpp
+++ b/clang/lib/CodeGen/Targets/SPIR.cpp
@@ -922,7 +922,7 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getSPIRVImageTypeFromHLSLResource(
IntParams[1] = 2;
// Arrayed
- IntParams[2] = 0;
+ IntParams[2] = static_cast<unsigned>(attributes.IsArray);
// MS
IntParams[3] = 0;
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 40e4f4024d6da..f8018729b4644 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1038,8 +1038,8 @@ BuiltinTypeDeclBuilder::addBufferHandles(ResourceClass RC, bool IsROV,
bool RawBuffer, bool HasCounter,
AccessSpecifier Access) {
QualType ElementTy = getHandleElementType();
- addHandleMember(RC, ResourceDimension::Unknown, IsROV, RawBuffer, ElementTy,
- Access);
+ addHandleMember(RC, ResourceDimension::Unknown, IsROV, RawBuffer,
+ /*IsArray=*/false, ElementTy, Access);
if (HasCounter)
addCounterHandleMember(RC, IsROV, RawBuffer, ElementTy, Access);
return *this;
@@ -1047,16 +1047,17 @@ BuiltinTypeDeclBuilder::addBufferHandles(ResourceClass RC, bool IsROV,
BuiltinTypeDeclBuilder &
BuiltinTypeDeclBuilder::addTextureHandle(ResourceClass RC, bool IsROV,
- ResourceDimension RD,
+ bool IsArray, ResourceDimension RD,
AccessSpecifier Access) {
- addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, getHandleElementType(),
- Access);
+ addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, IsArray,
+ getHandleElementType(), Access);
return *this;
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSamplerHandle() {
addHandleMember(ResourceClass::Sampler, ResourceDimension::Unknown,
- /*IsROV=*/false, /*RawBuffer=*/false, getHandleElementType());
+ /*IsROV=*/false, /*RawBuffer=*/false, /*IsArray=*/false,
+ getHandleElementType());
return *this;
}
@@ -1111,22 +1112,22 @@ CXXRecordDecl *BuiltinTypeDeclBuilder::addPrivateNestedRecord(StringRef Name) {
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
ResourceClass RC, ResourceDimension RD, bool IsROV, bool RawBuffer,
- QualType ElementTy, AccessSpecifier Access) {
+ bool IsArray, QualType ElementTy, AccessSpecifier Access) {
return addResourceMember("__handle", RC, RD, IsROV, RawBuffer,
- /*IsCounter=*/false, ElementTy, Access);
+ /*IsCounter=*/false, IsArray, ElementTy, Access);
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
ResourceClass RC, bool IsROV, bool RawBuffer, QualType ElementTy,
AccessSpecifier Access) {
return addResourceMember("__counter_handle", RC, ResourceDimension::Unknown,
- IsROV, RawBuffer,
- /*IsCounter=*/true, ElementTy, Access);
+ IsROV, RawBuffer, /*IsCounter=*/true,
+ /*IsArray=*/false, ElementTy, Access);
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember(
StringRef MemberName, ResourceClass RC, ResourceDimension RD, bool IsROV,
- bool RawBuffer, bool IsCounter, QualType ElementTy,
+ bool RawBuffer, bool IsCounter, bool IsArray, QualType ElementTy,
AccessSpecifier Access) {
assert(!Record->isCompleteDefinition() && "record is already complete");
@@ -1151,6 +1152,8 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember(
: nullptr};
if (IsCounter)
Attrs.push_back(HLSLIsCounterAttr::CreateImplicit(Ctx));
+ if (IsArray)
+ Attrs.push_back(HLSLIsArrayAttr::CreateImplicit(Ctx));
if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
AttributedResTy))
@@ -1405,13 +1408,14 @@ BuiltinTypeDeclBuilder::addCopyAssignmentOperator(AccessSpecifier Access) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addArraySubscriptOperators(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addArraySubscriptOperators(ResourceDimension Dim,
+ bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
uint32_t VecSize = 1;
if (Dim != ResourceDimension::Unknown)
- VecSize = getResourceDimensions(Dim);
+ VecSize = getResourceDimensions(Dim) + (IsArray ? 1 : 0);
QualType IndexTy = VecSize > 1
? AST.getExtVectorType(AST.UnsignedIntTy, VecSize)
@@ -1446,7 +1450,8 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() {
CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsSliceType(ResourceDimension Dim,
QualType ReturnType) {
ASTContext &AST = Record->getASTContext();
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t VecSize =
+ getResourceDimensions(Dim) + (getResourceAttrs().IsArray ? 1 : 0);
QualType IntTy = AST.IntTy;
QualType IndexTy = VecSize > 1 ? AST.getExtVectorType(IntTy, VecSize) : IntTy;
QualType CoordLevelTy = AST.getExtVectorType(IntTy, VecSize + 1);
@@ -1459,7 +1464,8 @@ CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsSliceType(ResourceDimension Dim,
BuiltinTypeDeclBuilder MipsSliceBuilder(SemaRef, MipsSliceRecord);
MipsSliceBuilder.addFriend(Record)
.addHandleMember(getResourceAttrs().ResourceClass, Dim,
- getResourceAttrs().IsROV, false, ReturnType,
+ getResourceAttrs().IsROV, /*RawBuffer=*/false,
+ getResourceAttrs().IsArray, ReturnType,
AccessSpecifier::AS_public)
.addMemberVariable("__level", IntTy, {}, AccessSpecifier::AS_public)
.addDefaultHandleConstructor(AccessSpecifier::AS_protected)
@@ -1502,7 +1508,8 @@ CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsType(ResourceDimension Dim,
BuiltinTypeDeclBuilder MipsBuilder(SemaRef, MipsRecord);
MipsBuilder.addFriend(Record)
.addHandleMember(getResourceAttrs().ResourceClass, Dim,
- getResourceAttrs().IsROV, false, ReturnType,
+ getResourceAttrs().IsROV, /*RawBuffer=*/false,
+ getResourceAttrs().IsArray, ReturnType,
AccessSpecifier::AS_public)
.addDefaultHandleConstructor(AccessSpecifier::AS_protected)
.addCopyConstructor(AccessSpecifier::AS_protected)
@@ -1553,13 +1560,15 @@ BuiltinTypeDeclBuilder::addMipsMember(ResourceDimension Dim) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addTextureLoadMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addTextureLoadMethods(ResourceDimension Dim,
+ bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 2 : 1);
QualType IntTy = AST.IntTy;
- QualType OffsetTy = AST.getExtVectorType(IntTy, VecSize);
- QualType LocationTy = AST.getExtVectorType(IntTy, VecSize + 1);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
+ QualType LocationTy = AST.getExtVectorType(IntTy, CoordSize);
QualType ReturnType = getHandleElementType();
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
@@ -1627,23 +1636,24 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addSampleMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addSampleMethods(ResourceDimension Dim, bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ReturnType = getHandleElementType();
QualType SamplerStateType =
lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
QualType FloatTy = AST.FloatTy;
- QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
+ QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
QualType IntTy = AST.IntTy;
- QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
// T Sample(SamplerState s, float2 location)
BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
PH::LastStmt, PH::_1)
@@ -1653,8 +1663,8 @@ BuiltinTypeDeclBuilder::addSampleMethods(ResourceDimension Dim) {
// T Sample(SamplerState s, float2 location, int2 offset)
BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
- .addParam("Offset", Int2Ty)
+ .addParam("Location", CoordTy)
+ .addParam("Offset", OffsetTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
PH::LastStmt, PH::_1, PH::_2)
@@ -1664,8 +1674,8 @@ BuiltinTypeDeclBuilder::addSampleMethods(ResourceDimension Dim) {
// T Sample(SamplerState s, float2 location, int2 offset, float clamp)
return BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
- .addParam("Offset", Int2Ty)
+ .addParam("Location", CoordTy)
+ .addParam("Offset", OffsetTy)
.addParam("Clamp", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
@@ -1675,23 +1685,25 @@ BuiltinTypeDeclBuilder::addSampleMethods(ResourceDimension Dim) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addSampleBiasMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addSampleBiasMethods(ResourceDimension Dim,
+ bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ReturnType = getHandleElementType();
QualType SamplerStateType =
lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
QualType FloatTy = AST.FloatTy;
- QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
+ QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
QualType IntTy = AST.IntTy;
- QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
// T SampleBias(SamplerState s, float2 location, float bias)
BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("Bias", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
@@ -1702,9 +1714,9 @@ BuiltinTypeDeclBuilder::addSampleBiasMethods(ResourceDimension Dim) {
// T SampleBias(SamplerState s, float2 location, float bias, int2 offset)
BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("Bias", FloatTy)
- .addParam("Offset", Int2Ty)
+ .addParam("Offset", OffsetTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
@@ -1715,9 +1727,9 @@ BuiltinTypeDeclBuilder::addSampleBiasMethods(ResourceDimension Dim) {
// float clamp)
return BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("Bias", FloatTy)
- .addParam("Offset", Int2Ty)
+ .addParam("Offset", OffsetTy)
.addParam("Clamp", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
@@ -1727,25 +1739,28 @@ BuiltinTypeDeclBuilder::addSampleBiasMethods(ResourceDimension Dim) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addSampleGradMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addSampleGradMethods(ResourceDimension Dim,
+ bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ReturnType = getHandleElementType();
QualType SamplerStateType =
lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
QualType FloatTy = AST.FloatTy;
- QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
+ QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
+ QualType OffsetFloatTy = AST.getExtVectorType(FloatTy, OffsetSize);
QualType IntTy = AST.IntTy;
- QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
// T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy)
BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
- .addParam("DDX", Float2Ty)
- .addParam("DDY", Float2Ty)
+ .addParam("Location", CoordTy)
+ .addParam("DDX", OffsetFloatTy)
+ .addParam("DDY", OffsetFloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
@@ -1756,10 +1771,10 @@ BuiltinTypeDeclBuilder::addSampleGradMethods(ResourceDimension Dim) {
// int2 offset)
BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
- .addParam("DDX", Float2Ty)
- .addParam("DDY", Float2Ty)
- .addParam("Offset", Int2Ty)
+ .addParam("Location", CoordTy)
+ .addParam("DDX", OffsetFloatTy)
+ .addParam("DDY", OffsetFloatTy)
+ .addParam("Offset", OffsetTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
@@ -1770,10 +1785,10 @@ BuiltinTypeDeclBuilder::addSampleGradMethods(ResourceDimension Dim) {
// int2 offset, float clamp)
return BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
- .addParam("DDX", Float2Ty)
- .addParam("DDY", Float2Ty)
- .addParam("Offset", Int2Ty)
+ .addParam("Location", CoordTy)
+ .addParam("DDX", OffsetFloatTy)
+ .addParam("DDY", OffsetFloatTy)
+ .addParam("Offset", OffsetTy)
.addParam("Clamp", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
@@ -1784,23 +1799,25 @@ BuiltinTypeDeclBuilder::addSampleGradMethods(ResourceDimension Dim) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addSampleLevelMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addSampleLevelMethods(ResourceDimension Dim,
+ bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ReturnType = getHandleElementType();
QualType SamplerStateType =
lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
QualType FloatTy = AST.FloatTy;
- QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
+ QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
QualType IntTy = AST.IntTy;
- QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
// T SampleLevel(SamplerState s, float2 location, float lod)
BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("LOD", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
@@ -1811,9 +1828,9 @@ BuiltinTypeDeclBuilder::addSampleLevelMethods(ResourceDimension Dim) {
// T SampleLevel(SamplerState s, float2 location, float lod, int2 offset)
return BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("LOD", FloatTy)
- .addParam("Offset", Int2Ty)
+ .addParam("Offset", OffsetTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
@@ -1822,23 +1839,25 @@ BuiltinTypeDeclBuilder::addSampleLevelMethods(ResourceDimension Dim) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addSampleCmpMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addSampleCmpMethods(ResourceDimension Dim,
+ bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ReturnType = AST.FloatTy;
QualType SamplerComparisonStateType = lookupBuiltinType(
SemaRef, "SamplerComparisonState", Record->getDeclContext());
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
QualType FloatTy = AST.FloatTy;
- QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
+ QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
QualType IntTy = AST.IntTy;
- QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
// T SampleCmp(SamplerComparisonState s, float2 location, float compare_value)
BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
.addParam("Sampler", SamplerComparisonStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("CompareValue", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
@@ -1850,9 +1869,9 @@ BuiltinTypeDeclBuilder::addSampleCmpMethods(ResourceDimension Dim) {
// int2 offset)
BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
.addParam("Sampler", SamplerComparisonStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("CompareValue", FloatTy)
- .addParam("Offset", Int2Ty)
+ .addParam("Offset", OffsetTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
PH::LastStmt, PH::_1, PH::_2, PH::_3)
@@ -1863,9 +1882,9 @@ BuiltinTypeDeclBuilder::addSampleCmpMethods(ResourceDimension Dim) {
// int2 offset, float clamp)
return BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
.addParam("Sampler", SamplerComparisonStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("CompareValue", FloatTy)
- .addParam("Offset", Int2Ty)
+ .addParam("Offset", OffsetTy)
.addParam("Clamp", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
@@ -1875,24 +1894,26 @@ BuiltinTypeDeclBuilder::addSampleCmpMethods(ResourceDimension Dim) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addSampleCmpLevelZeroMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addSampleCmpLevelZeroMethods(ResourceDimension Dim,
+ bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ReturnType = AST.FloatTy;
QualType SamplerComparisonStateType = lookupBuiltinType(
SemaRef, "SamplerComparisonState", Record->getDeclContext());
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
QualType FloatTy = AST.FloatTy;
- QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
+ QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
QualType IntTy = AST.IntTy;
- QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
// T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
// compare_value)
BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
.addParam("Sampler", SamplerComparisonStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("CompareValue", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
@@ -1904,9 +1925,9 @@ BuiltinTypeDeclBuilder::addSampleCmpLevelZeroMethods(ResourceDimension Dim) {
// compare_value, int2 offset)
return BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
.addParam("Sampler", SamplerComparisonStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("CompareValue", FloatTy)
- .addParam("Offset", Int2Ty)
+ .addParam("Offset", OffsetTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
@@ -2008,18 +2029,19 @@ QualType BuiltinTypeDeclBuilder::getGatherReturnType() {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addGatherMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addGatherMethods(ResourceDimension Dim, bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ReturnType = getGatherReturnType();
QualType SamplerStateType =
lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
QualType LocationTy = AST.FloatTy;
- QualType Float2Ty = AST.getExtVectorType(LocationTy, VecSize);
+ QualType CoordTy = AST.getExtVectorType(LocationTy, CoordSize);
QualType IntTy = AST.IntTy;
- QualType OffsetTy = AST.getExtVectorType(IntTy, VecSize);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
// Overloads for Gather, GatherRed, GatherGreen, GatherBlue, GatherAlpha
@@ -2037,7 +2059,7 @@ BuiltinTypeDeclBuilder::addGatherMethods(ResourceDimension Dim) {
// ret GatherVariant(SamplerState s, float2 location)
BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
PH::LastStmt, PH::_1,
@@ -2047,7 +2069,7 @@ BuiltinTypeDeclBuilder::addGatherMethods(ResourceDimension Dim) {
// ret GatherVariant(SamplerState s, float2 location, int2 offset)
BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
.addParam("Sampler", SamplerStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("Offset", OffsetTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
@@ -2060,18 +2082,20 @@ BuiltinTypeDeclBuilder::addGatherMethods(ResourceDimension Dim) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addGatherCmpMethods(ResourceDimension Dim) {
+BuiltinTypeDeclBuilder::addGatherCmpMethods(ResourceDimension Dim,
+ bool IsArray) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ReturnType = AST.getExtVectorType(AST.FloatTy, 4);
QualType SamplerComparisonStateType = lookupBuiltinType(
SemaRef, "SamplerComparisonState", Record->getDeclContext());
- uint32_t VecSize = getResourceDimensions(Dim);
+ uint32_t OffsetSize = getResourceDimensions(Dim);
+ uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
QualType FloatTy = AST.FloatTy;
- QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
+ QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
QualType IntTy = AST.IntTy;
- QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
+ QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
// Overloads for GatherCmp, GatherCmpRed, GatherCmpGreen, GatherCmpBlue,
@@ -2091,7 +2115,7 @@ BuiltinTypeDeclBuilder::addGatherCmpMethods(ResourceDimension Dim) {
// compare_value)
BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
.addParam("Sampler", SamplerComparisonStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("CompareValue", FloatTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
@@ -2103,9 +2127,9 @@ BuiltinTypeDeclBuilder::addGatherCmpMethods(ResourceDimension Dim) {
// compare_value, int2 offset)
BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
.addParam("Sampler", SamplerComparisonStateType)
- .addParam("Location", Float2Ty)
+ .addParam("Location", CoordTy)
.addParam("CompareValue", FloatTy)
- .addParam("Offset", Int2Ty)
+ .addParam("Offset", OffsetTy)
.accessHandleFieldOnResource(PH::_0)
.callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
PH::Handle, PH::LastStmt, PH::_1, PH::_2,
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index f8fc2eeb3af55..09cf1fceca116 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -80,12 +80,14 @@ class BuiltinTypeDeclBuilder {
bool HasCounter,
AccessSpecifier Access = AccessSpecifier::AS_private);
BuiltinTypeDeclBuilder &
- addTextureHandle(ResourceClass RC, bool IsROV, ResourceDimension RD,
+ addTextureHandle(ResourceClass RC, bool IsROV, bool IsArray,
+ ResourceDimension RD,
AccessSpecifier Access = AccessSpecifier::AS_private);
BuiltinTypeDeclBuilder &addSamplerHandle();
BuiltinTypeDeclBuilder &addConstantBufferConversionToType();
- BuiltinTypeDeclBuilder &addArraySubscriptOperators(
- ResourceDimension Dim = ResourceDimension::Unknown);
+ BuiltinTypeDeclBuilder &
+ addArraySubscriptOperators(ResourceDimension Dim = ResourceDimension::Unknown,
+ bool IsArray = false);
// Builtin types constructors
BuiltinTypeDeclBuilder &addDefaultHandleConstructor(
@@ -100,18 +102,27 @@ class BuiltinTypeDeclBuilder {
// Builtin types methods
BuiltinTypeDeclBuilder &addLoadMethods();
- BuiltinTypeDeclBuilder &addTextureLoadMethods(ResourceDimension Dim);
+ BuiltinTypeDeclBuilder &addTextureLoadMethods(ResourceDimension Dim,
+ bool IsArray = false);
BuiltinTypeDeclBuilder &addByteAddressBufferLoadMethods();
BuiltinTypeDeclBuilder &addByteAddressBufferStoreMethods();
- BuiltinTypeDeclBuilder &addSampleMethods(ResourceDimension Dim);
- BuiltinTypeDeclBuilder &addSampleBiasMethods(ResourceDimension Dim);
- BuiltinTypeDeclBuilder &addSampleGradMethods(ResourceDimension Dim);
- BuiltinTypeDeclBuilder &addSampleLevelMethods(ResourceDimension Dim);
- BuiltinTypeDeclBuilder &addSampleCmpMethods(ResourceDimension Dim);
- BuiltinTypeDeclBuilder &addSampleCmpLevelZeroMethods(ResourceDimension Dim);
+ BuiltinTypeDeclBuilder &addSampleMethods(ResourceDimension Dim,
+ bool IsArray = false);
+ BuiltinTypeDeclBuilder &addSampleBiasMethods(ResourceDimension Dim,
+ bool IsArray = false);
+ BuiltinTypeDeclBuilder &addSampleGradMethods(ResourceDimension Dim,
+ bool IsArray = false);
+ BuiltinTypeDeclBuilder &addSampleLevelMethods(ResourceDimension Dim,
+ bool IsArray = false);
+ BuiltinTypeDeclBuilder &addSampleCmpMethods(ResourceDimension Dim,
+ bool IsArray = false);
+ BuiltinTypeDeclBuilder &addSampleCmpLevelZeroMethods(ResourceDimension Dim,
+ bool IsArray = false);
BuiltinTypeDeclBuilder &addCalculateLodMethods(ResourceDimension Dim);
- BuiltinTypeDeclBuilder &addGatherMethods(ResourceDimension Dim);
- BuiltinTypeDeclBuilder &addGatherCmpMethods(ResourceDimension Dim);
+ BuiltinTypeDeclBuilder &addGatherMethods(ResourceDimension Dim,
+ bool IsArray = false);
+ BuiltinTypeDeclBuilder &addGatherCmpMethods(ResourceDimension Dim,
+ bool IsArray = false);
BuiltinTypeDeclBuilder &addIncrementCounterMethod();
BuiltinTypeDeclBuilder &addDecrementCounterMethod();
BuiltinTypeDeclBuilder &addHandleAccessFunction(DeclarationName &Name,
@@ -138,7 +149,7 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &
addResourceMember(StringRef MemberName, ResourceClass RC,
ResourceDimension RD, bool IsROV, bool RawBuffer,
- bool IsCounter, QualType ElementTy,
+ bool IsCounter, bool IsArray, QualType ElementTy,
AccessSpecifier Access = AccessSpecifier::AS_private);
BuiltinTypeDeclBuilder &addFriend(CXXRecordDecl *Friend);
CXXRecordDecl *addPrivateNestedRecord(StringRef Name);
@@ -146,7 +157,7 @@ class BuiltinTypeDeclBuilder {
CXXRecordDecl *addMipsType(ResourceDimension Dim, QualType ReturnType);
BuiltinTypeDeclBuilder &
addHandleMember(ResourceClass RC, ResourceDimension RD, bool IsROV,
- bool RawBuffer, QualType ElementTy,
+ bool RawBuffer, bool IsArray, QualType ElementTy,
AccessSpecifier Access = AccessSpecifier::AS_private);
BuiltinTypeDeclBuilder &
addCounterHandleMember(ResourceClass RC, bool IsROV, bool RawBuffer,
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 3f7255cb3f8a7..fec9175f6dc05 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -258,26 +258,27 @@ static BuiltinTypeDeclBuilder setupSamplerType(CXXRecordDecl *Decl, Sema &S) {
/// Set up common members and attributes for texture types
static BuiltinTypeDeclBuilder setupTextureType(CXXRecordDecl *Decl, Sema &S,
ResourceClass RC, bool IsROV,
+ bool IsArray,
ResourceDimension Dim) {
return BuiltinTypeDeclBuilder(S, Decl)
- .addTextureHandle(RC, IsROV, Dim)
- .addTextureLoadMethods(Dim)
- .addArraySubscriptOperators(Dim)
+ .addTextureHandle(RC, IsROV, IsArray, Dim)
+ .addTextureLoadMethods(Dim, IsArray)
+ .addArraySubscriptOperators(Dim, IsArray)
.addMipsMember(Dim)
.addDefaultHandleConstructor()
.addCopyConstructor()
.addCopyAssignmentOperator()
.addStaticInitializationFunctions(false)
- .addSampleMethods(Dim)
- .addSampleBiasMethods(Dim)
- .addSampleGradMethods(Dim)
- .addSampleLevelMethods(Dim)
- .addSampleCmpMethods(Dim)
- .addSampleCmpLevelZeroMethods(Dim)
+ .addSampleMethods(Dim, IsArray)
+ .addSampleBiasMethods(Dim, IsArray)
+ .addSampleGradMethods(Dim, IsArray)
+ .addSampleLevelMethods(Dim, IsArray)
+ .addSampleCmpMethods(Dim, IsArray)
+ .addSampleCmpLevelZeroMethods(Dim, IsArray)
.addCalculateLodMethods(Dim)
.addGetDimensionsMethods(Dim)
- .addGatherMethods(Dim)
- .addGatherCmpMethods(Dim);
+ .addGatherMethods(Dim, IsArray)
+ .addGatherCmpMethods(Dim, IsArray);
}
// Add a partial specialization for a template. The `TextureTemplate` is
@@ -678,7 +679,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupTextureType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
- ResourceDimension::Dim2D)
+ /*IsArray=*/false, ResourceDimension::Dim2D)
.completeDefinition();
});
@@ -686,7 +687,27 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
*SemaPtr, HLSLNamespace, Decl->getDescribedClassTemplate());
onCompletion(PartialSpec, [this](CXXRecordDecl *Decl) {
setupTextureType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
- ResourceDimension::Dim2D)
+ /*IsArray=*/false, ResourceDimension::Dim2D)
+ .completeDefinition();
+ });
+
+ // Texture2DArray — same as Texture2D but IsArray=true
+ Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "Texture2DArray")
+ .addSimpleTemplateParams({"element_type"}, {Float4Ty},
+ TypedBufferConcept)
+ .finalizeForwardDeclaration();
+
+ onCompletion(Decl, [this](CXXRecordDecl *Decl) {
+ setupTextureType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
+ /*IsArray=*/true, ResourceDimension::Dim2D)
+ .completeDefinition();
+ });
+
+ auto *PartialSpec2DA = addVectorTexturePartialSpecialization(
+ *SemaPtr, HLSLNamespace, Decl->getDescribedClassTemplate());
+ onCompletion(PartialSpec2DA, [this](CXXRecordDecl *Decl) {
+ setupTextureType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
+ /*IsArray=*/true, ResourceDimension::Dim2D)
.completeDefinition();
});
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 075dc97b0aef2..11e8d3c5dbf3c 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3686,7 +3686,8 @@ static bool CheckIndexType(Sema *S, CallExpr *TheCall, unsigned IndexArgIndex) {
unsigned int ExpectedDim = 1;
if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
- ExpectedDim = getResourceDimensions(ResAttrs.ResourceDimension);
+ ExpectedDim = getResourceDimensions(ResAttrs.ResourceDimension) +
+ (ResAttrs.IsArray ? 1 : 0);
if (ActualDim != ExpectedDim) {
S->Diag(TheCall->getArg(IndexArgIndex)->getBeginLoc(),
@@ -3741,7 +3742,8 @@ static bool CheckVectorElementCount(Sema *S, QualType PassedType,
enum class SampleKind { Sample, Bias, Grad, Level, Cmp, CmpLevelZero };
-static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall) {
+static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall,
+ bool IncludeArraySlice = true) {
// Check the texture handle.
if (CheckResourceHandle(&S, TheCall, 0,
[](const HLSLAttributedResourceType *ResType) {
@@ -3763,7 +3765,8 @@ static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall) {
// Check the location.
unsigned ExpectedDim =
- getResourceDimensions(ResourceTy->getAttrs().ResourceDimension);
+ getResourceDimensions(ResourceTy->getAttrs().ResourceDimension) +
+ (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
if (CheckVectorElementCount(&S, TheCall->getArg(2)->getType(),
S.Context.FloatTy, ExpectedDim,
TheCall->getBeginLoc()))
@@ -3776,7 +3779,9 @@ static bool CheckCalculateLodBuiltin(Sema &S, CallExpr *TheCall) {
if (S.checkArgCount(TheCall, 3))
return true;
- if (CheckTextureSamplerAndLocation(S, TheCall))
+ // CalculateLevelOfDetail location uses resource dimension only (e.g. float2
+ // for 2D), not an extra array slice component like Sample/Gather.
+ if (CheckTextureSamplerAndLocation(S, TheCall, /*IncludeArraySlice=*/false))
return true;
TheCall->setType(S.Context.FloatTy);
@@ -3882,11 +3887,12 @@ static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall) {
auto *ResourceTy =
TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
- // Check the location + lod (int3 for Texture2D).
- unsigned ExpectedDim =
+ // Check the location + lod (int3 for Texture2D, int4 for Texture2DArray).
+ unsigned ResourceDim =
getResourceDimensions(ResourceTy->getAttrs().ResourceDimension);
+ unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
QualType CoordLODTy = TheCall->getArg(1)->getType();
- if (CheckVectorElementCount(&S, CoordLODTy, S.Context.IntTy, ExpectedDim + 1,
+ if (CheckVectorElementCount(&S, CoordLODTy, S.Context.IntTy, LocationDim + 1,
TheCall->getArg(1)->getBeginLoc()))
return true;
@@ -3899,10 +3905,10 @@ static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall) {
return true;
}
- // Check the offset operand.
+ // Check the offset operand (int2 for 2D textures; no array slice).
if (TheCall->getNumArgs() > 2) {
if (CheckVectorElementCount(&S, TheCall->getArg(2)->getType(),
- S.Context.IntTy, ExpectedDim,
+ S.Context.IntTy, ResourceDim,
TheCall->getArg(2)->getBeginLoc()))
return true;
}
diff --git a/clang/test/AST/HLSL/Texture2DArray-scalar-AST.hlsl b/clang/test/AST/HLSL/Texture2DArray-scalar-AST.hlsl
new file mode 100644
index 0000000000000..8e853c9a7e954
--- /dev/null
+++ b/clang/test/AST/HLSL/Texture2DArray-scalar-AST.hlsl
@@ -0,0 +1,931 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -disable-llvm-passes -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK: CXXRecordDecl {{.*}} SamplerState definition
+// CHECK: FinalAttr {{.*}} Implicit final
+// CHECK-NEXT: FieldDecl {{.*}} implicit {{.*}} __handle '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+
+// CHECK: CXXRecordDecl {{.*}} SamplerComparisonState definition
+// CHECK: FinalAttr {{.*}} Implicit final
+// CHECK-NEXT: FieldDecl {{.*}} implicit {{.*}} __handle '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+
+// CHECK: ClassTemplateDecl {{.*}} Texture2DArray
+// CHECK: TemplateTypeParmDecl {{.*}} element_type
+// CHECK: CXXRecordDecl {{.*}} Texture2DArray definition
+// CHECK: FinalAttr {{.*}} Implicit final
+// CHECK-NEXT: FieldDecl {{.*}} implicit __handle '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+
+// CHECK: CXXMethodDecl {{.*}} Load 'element_type (vector<int, 4>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<int, 4>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_level' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 4>' lvalue ParmVar {{.*}} 'Location' 'vector<int, 4>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Load 'element_type (vector<int, 4>, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<int, 4>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_level' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 4>' lvalue ParmVar {{.*}} 'Location' 'vector<int, 4>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} operator[] 'const hlsl_device element_type &(vector<unsigned int, 3>) const' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Index 'vector<unsigned int, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'hlsl_device element_type *' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'const hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 3>' lvalue ParmVar {{.*}} 'Index' 'vector<unsigned int, 3>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Sample 'element_type (hlsl::SamplerState, vector<float, 3>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Sample 'element_type (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Sample 'element_type (hlsl::SamplerState, vector<float, 3>, vector<int, 2>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Clamp 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleBias 'element_type (hlsl::SamplerState, vector<float, 3>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Bias 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_bias' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Bias' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleBias 'element_type (hlsl::SamplerState, vector<float, 3>, float, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Bias 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_bias' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Bias' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleBias 'element_type (hlsl::SamplerState, vector<float, 3>, float, vector<int, 2>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Bias 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Clamp 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_bias' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Bias' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleGrad 'element_type (hlsl::SamplerState, vector<float, 3>, vector<float, 2>, vector<float, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDX 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDY 'vector<float, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_grad' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDX' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDY' 'vector<float, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleGrad 'element_type (hlsl::SamplerState, vector<float, 3>, vector<float, 2>, vector<float, 2>, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDX 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDY 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_grad' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDX' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDY' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleGrad 'element_type (hlsl::SamplerState, vector<float, 3>, vector<float, 2>, vector<float, 2>, vector<int, 2>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDX 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDY 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Clamp 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_grad' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDX' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDY' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleLevel 'element_type (hlsl::SamplerState, vector<float, 3>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} LOD 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_level' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'LOD' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleLevel 'element_type (hlsl::SamplerState, vector<float, 3>, float, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} LOD 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_level' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'LOD' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmp 'float (hlsl::SamplerComparisonState, vector<float, 3>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmp 'float (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmp 'float (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Clamp 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmpLevelZero 'float (hlsl::SamplerComparisonState, vector<float, 3>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp_level_zero' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmpLevelZero 'float (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp_level_zero' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} CalculateLevelOfDetail 'float (hlsl::SamplerState, vector<float, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_calculate_lod' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} CalculateLevelOfDetailUnclamped 'float (hlsl::SamplerState, vector<float, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_calculate_lod_unclamped' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int, out unsigned int)'
+// CHECK-NEXT: ParmVarDecl {{.*}} width 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} height 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_xy' 'void (__hlsl_resource_t, unsigned int &, unsigned int &) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'width' 'unsigned int &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'height' 'unsigned int &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, out unsigned int, out unsigned int, out unsigned int)'
+// CHECK-NEXT: ParmVarDecl {{.*}} mipLevel 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} width 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} height 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} numberOfLevels 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_levels_xy' 'void (__hlsl_resource_t, unsigned int, unsigned int &, unsigned int &, unsigned int &) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'mipLevel' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'width' 'unsigned int &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'height' 'unsigned int &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'numberOfLevels' 'unsigned int &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out float, out float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} width 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} height 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_xy_float' 'void (__hlsl_resource_t, float &, float &) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'width' 'float &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'height' 'float &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, out float, out float, out float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} mipLevel 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} width 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} height 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} numberOfLevels 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_levels_xy_float' 'void (__hlsl_resource_t, unsigned int, float &, float &, float &) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'mipLevel' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'width' 'float &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'height' 'float &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'numberOfLevels' 'float &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Gather 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Gather 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherRed 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherRed 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherGreen 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherGreen 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherBlue 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherBlue 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherAlpha 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherAlpha 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmp 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmp 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmpRed 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmpGreen 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmpBlue 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmpAlpha 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+Texture2DArray<float> t;
+SamplerState s;
+SamplerComparisonState scs;
+
+void main(float3 loc, float cmp) {
+ t.Sample(s, loc);
+ t.Sample(s, loc, int2(1, 2));
+ t.Sample(s, loc, int2(1, 2), 1.0);
+ t.SampleBias(s, loc, 0.0);
+ t.SampleBias(s, loc, 0.0, int2(1, 2));
+ t.SampleBias(s, loc, 0.0, int2(1, 2), 1.0);
+ t.SampleGrad(s, loc, float2(0,0), float2(0,0));
+ t.SampleGrad(s, loc, float2(0,0), float2(0,0), int2(1, 2));
+ t.SampleGrad(s, loc, float2(0,0), float2(0,0), int2(1, 2), 1.0);
+ t.SampleLevel(s, loc, 0.0);
+ t.SampleLevel(s, loc, 0.0, int2(1, 2));
+ t.SampleCmp(scs, loc, cmp);
+ t.SampleCmp(scs, loc, cmp, int2(1, 2));
+ t.SampleCmp(scs, loc, cmp, int2(1, 2), 1.0f);
+ t.SampleCmpLevelZero(scs, loc, cmp);
+ t.SampleCmpLevelZero(scs, loc, cmp, int2(1, 2));
+ t.CalculateLevelOfDetail(s, loc.xy);
+ t.CalculateLevelOfDetailUnclamped(s, loc.xy);
+ t.Gather(s, loc);
+ uint u_w, u_h, u_l;
+ float f_w, f_h, f_l;
+ t.GetDimensions(u_w, u_h);
+ t.GetDimensions(0, u_w, u_h, u_l);
+ t.GetDimensions(f_w, f_h);
+ t.GetDimensions(0, f_w, f_h, f_l);
+}
diff --git a/clang/test/AST/HLSL/Texture2DArray-shorthand-AST.hlsl b/clang/test/AST/HLSL/Texture2DArray-shorthand-AST.hlsl
new file mode 100644
index 0000000000000..2c1aa6e2fd4ca
--- /dev/null
+++ b/clang/test/AST/HLSL/Texture2DArray-shorthand-AST.hlsl
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -disable-llvm-passes -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK: VarDecl {{.*}} t1 'hlsl::Texture2DArray<vector<float, 4>>':'hlsl::Texture2DArray<>'
+Texture2DArray t1;
+
+// CHECK: VarDecl {{.*}} t1_explicit 'Texture2DArray<>':'hlsl::Texture2DArray<>'
+Texture2DArray<> t1_explicit;
+
+// CHECK: VarDecl {{.*}} t2 'Texture2DArray<float>':'hlsl::Texture2DArray<float>'
+Texture2DArray<float> t2;
+
+// CHECK: VarDecl {{.*}} t3 'Texture2DArray<float4>':'hlsl::Texture2DArray<>'
+Texture2DArray<float4> t3;
+
+// CHECK: TypedefDecl {{.*}} tex_alias 'hlsl::Texture2DArray<vector<float, 4>>':'hlsl::Texture2DArray<>'
+typedef Texture2DArray tex_alias;
+
+struct S {
+ // CHECK: FieldDecl {{.*}} tex 'hlsl::Texture2DArray<vector<float, 4>>':'hlsl::Texture2DArray<>'
+ Texture2DArray tex;
+};
+
+// CHECK: FunctionDecl {{.*}} foo 'hlsl::Texture2DArray<vector<float, 4>> (hlsl::Texture2DArray<vector<float, 4>>)'
+// CHECK: ParmVarDecl {{.*}} p 'hlsl::Texture2DArray<vector<float, 4>>':'hlsl::Texture2DArray<>'
+Texture2DArray foo(Texture2DArray p) {
+ // CHECK: VarDecl {{.*}} local 'hlsl::Texture2DArray<vector<float, 4>>':'hlsl::Texture2DArray<>'
+ Texture2DArray local;
+ return local;
+}
+
+template<typename T>
+void template_foo(T p) {
+ // CHECK: VarDecl {{.*}} local 'hlsl::Texture2DArray<vector<float, 4>>':'hlsl::Texture2DArray<>'
+ Texture2DArray local;
+}
+
+void main() {
+ template_foo(1);
+}
diff --git a/clang/test/AST/HLSL/Texture2DArray-vector-AST.hlsl b/clang/test/AST/HLSL/Texture2DArray-vector-AST.hlsl
new file mode 100644
index 0000000000000..390007672c18a
--- /dev/null
+++ b/clang/test/AST/HLSL/Texture2DArray-vector-AST.hlsl
@@ -0,0 +1,931 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -disable-llvm-passes -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK: CXXRecordDecl {{.*}} SamplerState definition
+// CHECK: FinalAttr {{.*}} Implicit final
+// CHECK-NEXT: FieldDecl {{.*}} implicit {{.*}} __handle '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+
+// CHECK: CXXRecordDecl {{.*}} SamplerComparisonState definition
+// CHECK: FinalAttr {{.*}} Implicit final
+// CHECK-NEXT: FieldDecl {{.*}} implicit {{.*}} __handle '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+
+// CHECK: ClassTemplateDecl {{.*}} Texture2DArray
+// CHECK: TemplateTypeParmDecl {{.*}} element_type
+// CHECK: CXXRecordDecl {{.*}} Texture2DArray
+// CHECK: FinalAttr {{.*}} Implicit final
+// CHECK: ClassTemplatePartialSpecializationDecl {{.*}} Texture2DArray definition explicit_specialization
+// CHECK: TemplateArgument type 'vector<element_type, element_count>':'vector<type-parameter-0-0, element_count>'
+// CHECK: TemplateTypeParmDecl {{.*}} element_type
+// CHECK: NonTypeTemplateParmDecl {{.*}} element_count
+// CHECK-NEXT: FieldDecl {{.*}} implicit __handle '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+
+// CHECK: CXXMethodDecl {{.*}} Load 'vector<element_type, element_count> (vector<int, 4>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<int, 4>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_level' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 4>' lvalue ParmVar {{.*}} 'Location' 'vector<int, 4>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Load 'vector<element_type, element_count> (vector<int, 4>, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<int, 4>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_level' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 4>' lvalue ParmVar {{.*}} 'Location' 'vector<int, 4>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} operator[] 'vector<element_type, element_count> const hlsl_device &(vector<unsigned int, 3>) const' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Index 'vector<unsigned int, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: UnaryOperator {{.*}} 'vector<element_type, element_count> hlsl_device' lvalue prefix '*' cannot overflow
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count> hlsl_device *' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'const hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 3>' lvalue ParmVar {{.*}} 'Index' 'vector<unsigned int, 3>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Sample 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Sample 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Sample 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Clamp 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleBias 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Bias 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_bias' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Bias' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleBias 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, float, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Bias 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_bias' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Bias' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleBias 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, float, vector<int, 2>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Bias 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Clamp 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_bias' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Bias' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleGrad 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, vector<float, 2>, vector<float, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDX 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDY 'vector<float, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_grad' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDX' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDY' 'vector<float, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleGrad 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, vector<float, 2>, vector<float, 2>, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDX 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDY 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_grad' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDX' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDY' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleGrad 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, vector<float, 2>, vector<float, 2>, vector<int, 2>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDX 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} DDY 'vector<float, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Clamp 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_grad' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDX' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'DDY' 'vector<float, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleLevel 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} LOD 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_level' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'LOD' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleLevel 'vector<element_type, element_count> (hlsl::SamplerState, vector<float, 3>, float, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} LOD 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, element_count>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_level' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'LOD' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmp 'float (hlsl::SamplerComparisonState, vector<float, 3>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmp 'float (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmp 'float (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Clamp 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmpLevelZero 'float (hlsl::SamplerComparisonState, vector<float, 3>, float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp_level_zero' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} SampleCmpLevelZero 'float (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_sample_cmp_level_zero' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} CalculateLevelOfDetail 'float (hlsl::SamplerState, vector<float, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_calculate_lod' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} CalculateLevelOfDetailUnclamped 'float (hlsl::SamplerState, vector<float, 2>)'
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_calculate_lod_unclamped' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int, out unsigned int)'
+// CHECK-NEXT: ParmVarDecl {{.*}} width 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} height 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_hlsl_resource_getdimensions_xy' 'void (__hlsl_resource_t, unsigned int &, unsigned int &) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'width' 'unsigned int &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'height' 'unsigned int &__restrict'
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, out unsigned int, out unsigned int, out unsigned int)'
+// CHECK-NEXT: ParmVarDecl {{.*}} mipLevel 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} width 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} height 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} numberOfLevels 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_hlsl_resource_getdimensions_levels_xy' 'void (__hlsl_resource_t, unsigned int, unsigned int &, unsigned int &, unsigned int &) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'mipLevel' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'width' 'unsigned int &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'height' 'unsigned int &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'numberOfLevels' 'unsigned int &__restrict'
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out float, out float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} width 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} height 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_hlsl_resource_getdimensions_xy_float' 'void (__hlsl_resource_t, float &, float &) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'width' 'float &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'height' 'float &__restrict'
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, out float, out float, out float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} mipLevel 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} width 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} height 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} numberOfLevels 'float &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_hlsl_resource_getdimensions_levels_xy_float' 'void (__hlsl_resource_t, unsigned int, float &, float &, float &) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::is_array]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<element_type, element_count>)]]
+// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]]
+// CHECK-SAME: ' lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<vector<element_type, element_count>>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'mipLevel' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'width' 'float &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'height' 'float &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'numberOfLevels' 'float &__restrict'
+
+// CHECK: CXXMethodDecl {{.*}} Gather 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} Gather 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherRed 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherRed 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherGreen 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherGreen 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherBlue 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherBlue 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherAlpha 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherAlpha 'vector<element_type, 4> (hlsl::SamplerState, vector<float, 3>, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<element_type, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmp 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmp 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmpRed 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmpGreen 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmpBlue 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
+// CHECK-NEXT: AlwaysInlineAttr
+
+// CHECK: CXXMethodDecl {{.*}} GatherCmpAlpha 'vector<float, 4> (hlsl::SamplerComparisonState, vector<float, 3>, float, vector<int, 2>)' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 3>'
+// CHECK-NEXT: ParmVarDecl {{.*}} CompareValue 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} Offset 'vector<int, 2>'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CStyleCastExpr {{.*}} 'vector<float, 4>' <Dependent>
+// CHECK-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_gather_cmp' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2DArray<{{.*}}>' lvalue implicit this
+// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::SamplerComparisonState' lvalue ParmVar {{.*}} 'Sampler' 'hlsl::SamplerComparisonState'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 3>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>'
+// CHECK-NEXT: AlwaysInlineAttr
+
+Texture2DArray<float4> t;
+SamplerState s;
+SamplerComparisonState scs;
+
+void main(float3 loc, float cmp) {
+ t.Sample(s, loc);
+ t.Sample(s, loc, int2(1, 2));
+ t.Sample(s, loc, int2(1, 2), 1.0);
+ t.SampleBias(s, loc, 0.0);
+ t.SampleBias(s, loc, 0.0, int2(1, 2));
+ t.SampleBias(s, loc, 0.0, int2(1, 2), 1.0);
+ t.SampleGrad(s, loc, float2(0,0), float2(0,0));
+ t.SampleGrad(s, loc, float2(0,0), float2(0,0), int2(1, 2));
+ t.SampleGrad(s, loc, float2(0,0), float2(0,0), int2(1, 2), 1.0);
+ t.SampleLevel(s, loc, 0.0);
+ t.SampleLevel(s, loc, 0.0, int2(1, 2));
+ t.SampleCmp(scs, loc, cmp);
+ t.SampleCmp(scs, loc, cmp, int2(1, 2));
+ t.SampleCmp(scs, loc, cmp, int2(1, 2), 1.0f);
+ t.SampleCmpLevelZero(scs, loc, cmp);
+ t.SampleCmpLevelZero(scs, loc, cmp, int2(1, 2));
+ t.CalculateLevelOfDetail(s, loc.xy);
+ t.CalculateLevelOfDetailUnclamped(s, loc.xy);
+ t.Gather(s, loc);
+ uint u_w, u_h, u_l;
+ float f_w, f_h, f_l;
+ t.GetDimensions(u_w, u_h);
+ t.GetDimensions(0, u_w, u_h, u_l);
+ t.GetDimensions(f_w, f_h);
+ t.GetDimensions(0, f_w, f_h, f_l);
+}
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-CalculateLevelOfDetail.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-CalculateLevelOfDetail.hlsl
new file mode 100644
index 0000000000000..eebde4aacdbf6
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-CalculateLevelOfDetail.hlsl
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+Texture2DArray t;
+SamplerState s;
+
+// CHECK: define hidden {{.*}} float @test_lod(float vector[2])(<2 x float> {{.*}} %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} float @hlsl::Texture2DArray<float vector[4]>::CalculateLevelOfDetail(hlsl::SamplerState, float vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 x float> {{.*}} %{{.*}})
+// CHECK: ret float %[[CALL]]
+
+float test_lod(float2 loc : LOC) : SV_Target {
+ return t.CalculateLevelOfDetail(s, loc);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float vector[4]>::CalculateLevelOfDetail(hlsl::SamplerState, float vector[2])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <2 x float> {{.*}} %[[COORD:[^)]+]])
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <2 x float>, ptr %[[COORD]]
+// DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.resource.calculate.lod.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v2f32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <2 x float> %[[COORD_VAL]])
+// SPIRV: %[[RES:.*]] = call {{.*}} float @llvm.spv.resource.calculate.lod.f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v2f32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <2 x float> %[[COORD_VAL]])
+// CHECK: ret float %[[RES]]
+
+// CHECK: define hidden {{.*}} float @test_lod_unclamped(float vector[2])(<2 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[LOC_VAL:.*]] = load <2 x float>, ptr {{.*}}
+// CHECK: %[[CALL:.*]] = call {{.*}} float @hlsl::Texture2DArray<float vector[4]>::CalculateLevelOfDetailUnclamped(hlsl::SamplerState, float vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 x float> {{.*}} %[[LOC_VAL]])
+// CHECK: ret float %[[CALL]]
+
+float test_lod_unclamped(float2 loc : LOC) : SV_Target {
+ return t.CalculateLevelOfDetailUnclamped(s, loc);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float vector[4]>::CalculateLevelOfDetailUnclamped(hlsl::SamplerState, float vector[2])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <2 x float> {{.*}} %[[COORD:[^)]+]])
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <2 x float>, ptr %[[COORD]]
+// DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.resource.calculate.lod.unclamped.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v2f32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <2 x float> %[[COORD_VAL]])
+// SPIRV: %[[RES:.*]] = call {{.*}} float @llvm.spv.resource.calculate.lod.unclamped.f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v2f32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <2 x float> %[[COORD_VAL]])
+// CHECK: ret float %[[RES]]
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-Gather.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-Gather.hlsl
new file mode 100644
index 0000000000000..38b348de6124f
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-Gather.hlsl
@@ -0,0 +1,183 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+// DXIL: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) }
+// DXIL: %"class.hlsl::SamplerComparisonState" = type { target("dx.Sampler", 0) }
+
+// SPIRV: %"class.hlsl::Texture2DArray" = type { target("spirv.Image", float, 1, 2, 1, 0, 1, 0), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") }
+// SPIRV: %"class.hlsl::SamplerComparisonState" = type { target("spirv.Sampler") }
+
+Texture2DArray<float4> t;
+SamplerState s;
+SamplerComparisonState sc;
+
+// CHECK: define hidden {{.*}} <4 x float> @main(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Gather(hlsl::SamplerState, float vector[3])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}})
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 main(float3 loc : LOC) : SV_Target {
+ return t.Gather(s, loc);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Gather(hlsl::SamplerState, float vector[3])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.gather.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 0, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 0, <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_offset(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Gather(hlsl::SamplerState, float vector[3], int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, <2 x i32> {{.*}} <i32 1, i32 2>)
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_offset(float3 loc : LOC) : SV_Target {
+ return t.Gather(s, loc, int2(1, 2));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Gather(hlsl::SamplerState, float vector[3], int vector[2])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^,]+]], <2 x i32> {{.*}} %[[OFFSET:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: %[[OFFSET_ADDR:.*]] = alloca <2 x i32>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: store <2 x i32> %[[OFFSET]], ptr %[[OFFSET_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// CHECK: %[[OFFSET_VAL:.*]] = load <2 x i32>, ptr %[[OFFSET_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.gather.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 0, <2 x i32> %[[OFFSET_VAL]])
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 0, <2 x i32> %[[OFFSET_VAL]])
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_green(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherGreen(hlsl::SamplerState, float vector[3])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}})
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_green(float3 loc : LOC) : SV_Target {
+ return t.GatherGreen(s, loc);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherGreen(hlsl::SamplerState, float vector[3])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.gather.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 1, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 1, <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_red(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherRed(hlsl::SamplerState, float vector[3])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}})
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_red(float3 loc : LOC) : SV_Target {
+ return t.GatherRed(s, loc);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherRed(hlsl::SamplerState, float vector[3])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.gather.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 0, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 0, <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_blue(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherBlue(hlsl::SamplerState, float vector[3])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}})
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_blue(float3 loc : LOC) : SV_Target {
+ return t.GatherBlue(s, loc);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherBlue(hlsl::SamplerState, float vector[3])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.gather.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 2, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 2, <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_alpha(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherAlpha(hlsl::SamplerState, float vector[3])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}})
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_alpha(float3 loc : LOC) : SV_Target {
+ return t.GatherAlpha(s, loc);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherAlpha(hlsl::SamplerState, float vector[3])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.gather.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 3, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], i32 3, <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_cmp(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherCmp(hlsl::SamplerComparisonState, float vector[3], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 5.000000e-01)
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_cmp(float3 loc : LOC) : SV_Target {
+ return t.GatherCmp(sc, loc, 0.5);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::GatherCmp(hlsl::SamplerComparisonState, float vector[3], float)(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^,]+]], float {{.*}} %[[CMP:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: %[[CMP_ADDR:.*]] = alloca float
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: store float %[[CMP]], ptr %[[CMP_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerComparisonState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// CHECK: %[[CMP_VAL:.*]] = load float, ptr %[[CMP_ADDR]]
+// CHECK: %[[CONV:.*]] = fpext {{.*}} float %[[CMP_VAL]] to double
+// CHECK: %[[TRUNC:.*]] = fptrunc {{.*}} double %[[CONV]] to float
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.gather.cmp.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], float %[[TRUNC]], i32 0, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.gather.cmp.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], float %[[TRUNC]], <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-GetDimensions.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-GetDimensions.hlsl
new file mode 100644
index 0000000000000..f295839be4887
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-GetDimensions.hlsl
@@ -0,0 +1,103 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+Texture2DArray<float4> Tex : register(t0);
+
+// CHECK: define {{.*}} void @test_uint_dims()
+// CHECK: call void @hlsl::Texture2DArray<float vector[4]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @Tex, ptr {{.*}}, ptr {{.*}})
+void test_uint_dims() {
+ uint w, h;
+ Tex.GetDimensions(w, h);
+}
+
+// TODO: The test will have to be updated because the return type for the getdimensions intrinsic will no longer a overloaded.
+
+// CHECK: define linkonce_odr hidden void @hlsl::Texture2DArray<float vector[4]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} %[[THIS:.*]], ptr {{.*}} %[[WIDTH:.*]], ptr {{.*}} %[[HEIGHT:.*]])
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 7), ptr %[[HANDLE_GEP]]
+// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 1, 0, 1, 0), ptr %[[HANDLE_GEP]]
+// DXIL: %[[RES:.*]] = call <2 x i32> @llvm.dx.resource.getdimensions.xy.tdx.Texture_v4f32_0_0_0_7t(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]])
+// SPIRV: %[[RES:.*]] = call <2 x i32> @llvm.spv.resource.getdimensions.xy.tspirv.Image_f32_1_2_1_0_1_0t(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]])
+// CHECK: %[[W_PTR:.*]] = load ptr, ptr %[[WIDTH]]
+// CHECK: %[[W_VAL:.*]] = extractelement <2 x i32> %[[RES]], i64 0
+// CHECK: store i32 %[[W_VAL]], ptr %[[W_PTR]]
+// CHECK: %[[H_PTR:.*]] = load ptr, ptr %[[HEIGHT]]
+// CHECK: %[[H_VAL:.*]] = extractelement <2 x i32> %[[RES]], i64 1
+// CHECK: store i32 %[[H_VAL]], ptr %[[H_PTR]]
+
+// CHECK: define {{.*}} void @test_uint_levels_dims{{.*}}(i32 noundef %[[MIP_LEVEL:.*]])
+// CHECK: call void @hlsl::Texture2DArray<float vector[4]>::GetDimensions(unsigned int, unsigned int&, unsigned int&, unsigned int&)(ptr {{.*}} @Tex, i32 noundef %{{.*}}, ptr {{.*}}, ptr {{.*}}, ptr {{.*}})
+void test_uint_levels_dims(uint mipLevel) {
+ uint w, h, l;
+ Tex.GetDimensions(mipLevel, w, h, l);
+}
+
+// CHECK: define linkonce_odr hidden void @hlsl::Texture2DArray<float vector[4]>::GetDimensions(unsigned int, unsigned int&, unsigned int&, unsigned int&)(ptr {{.*}} %[[THIS:.*]], i32 {{.*}} %[[MIP:.*]], ptr {{.*}} %[[WIDTH:.*]], ptr {{.*}} %[[HEIGHT:.*]], ptr {{.*}} %[[LEVELS:.*]])
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 7), ptr %[[HANDLE_GEP]]
+// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 1, 0, 1, 0), ptr %[[HANDLE_GEP]]
+// CHECK: %[[MIP_VAL:.*]] = load i32, ptr %[[MIP]]
+// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.getdimensions.levels.xy.tdx.Texture_v4f32_0_0_0_7t(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], i32 %[[MIP_VAL]])
+// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.tspirv.Image_f32_1_2_1_0_1_0t(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], i32 %[[MIP_VAL]])
+// CHECK: %[[W_PTR:.*]] = load ptr, ptr %[[WIDTH]]
+// CHECK: %[[W_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 0
+// CHECK: store i32 %[[W_VAL]], ptr %[[W_PTR]]
+// CHECK: %[[H_PTR:.*]] = load ptr, ptr %[[HEIGHT]]
+// CHECK: %[[H_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 1
+// CHECK: store i32 %[[H_VAL]], ptr %[[H_PTR]]
+// CHECK: %[[L_PTR:.*]] = load ptr, ptr %[[LEVELS]]
+// CHECK: %[[L_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 2
+// CHECK: store i32 %[[L_VAL]], ptr %[[L_PTR]]
+
+// CHECK: define {{.*}} void @test_float_dims()
+// CHECK: call void @hlsl::Texture2DArray<float vector[4]>::GetDimensions(float&, float&)(ptr {{.*}} @Tex, ptr {{.*}}, ptr {{.*}})
+void test_float_dims() {
+ float w, h;
+ Tex.GetDimensions(w, h);
+}
+
+// CHECK: define linkonce_odr hidden void @hlsl::Texture2DArray<float vector[4]>::GetDimensions(float&, float&)(ptr {{.*}} %[[THIS:.*]], ptr {{.*}} %[[WIDTH:.*]], ptr {{.*}} %[[HEIGHT:.*]])
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 7), ptr %[[HANDLE_GEP]]
+// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 1, 0, 1, 0), ptr %[[HANDLE_GEP]]
+// DXIL: %[[RES:.*]] = call <2 x i32> @llvm.dx.resource.getdimensions.xy.tdx.Texture_v4f32_0_0_0_7t(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]])
+// SPIRV: %[[RES:.*]] = call <2 x i32> @llvm.spv.resource.getdimensions.xy.tspirv.Image_f32_1_2_1_0_1_0t(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]])
+// CHECK: %[[W_PTR:.*]] = load ptr, ptr %[[WIDTH]]
+// CHECK: %[[W_VAL:.*]] = extractelement <2 x i32> %[[RES]], i64 0
+// CHECK: %[[W_F:.*]] = uitofp reassoc nnan ninf nsz arcp afn i32 %[[W_VAL]] to float
+// CHECK: store float %[[W_F]], ptr %[[W_PTR]]
+// CHECK: %[[H_PTR:.*]] = load ptr, ptr %[[HEIGHT]]
+// CHECK: %[[H_VAL:.*]] = extractelement <2 x i32> %[[RES]], i64 1
+// CHECK: %[[H_F:.*]] = uitofp reassoc nnan ninf nsz arcp afn i32 %[[H_VAL]] to float
+// CHECK: store float %[[H_F]], ptr %[[H_PTR]]
+
+// CHECK: define {{.*}} void @test_float_levels_dims{{.*}}(i32 noundef %[[MIP_LEVEL:.*]])
+// CHECK: call void @hlsl::Texture2DArray<float vector[4]>::GetDimensions(unsigned int, float&, float&, float&)(ptr {{.*}} @Tex, i32 noundef %{{.*}}, ptr {{.*}}, ptr {{.*}}, ptr {{.*}})
+void test_float_levels_dims(uint mipLevel) {
+ float w, h, l;
+ Tex.GetDimensions(mipLevel, w, h, l);
+}
+
+// CHECK: define linkonce_odr hidden void @hlsl::Texture2DArray<float vector[4]>::GetDimensions(unsigned int, float&, float&, float&)(ptr {{.*}} %[[THIS:.*]], i32 {{.*}} %[[MIP:.*]], ptr {{.*}} %[[WIDTH:.*]], ptr {{.*}} %[[HEIGHT:.*]], ptr {{.*}} %[[LEVELS:.*]])
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 7), ptr %[[HANDLE_GEP]]
+// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 1, 0, 1, 0), ptr %[[HANDLE_GEP]]
+// CHECK: %[[MIP_VAL:.*]] = load i32, ptr %[[MIP]]
+// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.getdimensions.levels.xy.tdx.Texture_v4f32_0_0_0_7t(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], i32 %[[MIP_VAL]])
+// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.tspirv.Image_f32_1_2_1_0_1_0t(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], i32 %[[MIP_VAL]])
+// CHECK: %[[W_PTR:.*]] = load ptr, ptr %[[WIDTH]]
+// CHECK: %[[W_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 0
+// CHECK: %[[W_F:.*]] = uitofp reassoc nnan ninf nsz arcp afn i32 %[[W_VAL]] to float
+// CHECK: store float %[[W_F]], ptr %[[W_PTR]]
+// CHECK: %[[H_PTR:.*]] = load ptr, ptr %[[HEIGHT]]
+// CHECK: %[[H_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 1
+// CHECK: %[[H_F:.*]] = uitofp reassoc nnan ninf nsz arcp afn i32 %[[H_VAL]] to float
+// CHECK: store float %[[H_F]], ptr %[[H_PTR]]
+// CHECK: %[[L_PTR:.*]] = load ptr, ptr %[[LEVELS]]
+// CHECK: %[[L_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 2
+// CHECK: %[[L_F:.*]] = uitofp reassoc nnan ninf nsz arcp afn i32 %[[L_VAL]] to float
+// CHECK: store float %[[L_F]], ptr %[[L_PTR]]
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-Load.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-Load.hlsl
new file mode 100644
index 0000000000000..02909846c9833
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-Load.hlsl
@@ -0,0 +1,236 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+Texture2DArray<float4> t;
+
+// CHECK: define hidden {{.*}} <4 x float> @test_load(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Load(int vector[4])(ptr {{.*}} @t, <4 x i32> noundef %{{.*}})
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_load(int2 loc : LOC) : SV_Target {
+ return t.Load(int4(loc, 0, 0));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Load(int vector[4])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[LOCATION_ADDR:.*]] = alloca <4 x i32>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <4 x i32> %[[LOCATION]], ptr %[[LOCATION_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target("{{(dx.Texture|spirv.Image)}}", {{.*}}), ptr %[[HANDLE_GEP]]
+// CHECK: %[[LOCATION_VAL:.*]] = load <4 x i32>, ptr %[[LOCATION_ADDR]]
+// CHECK: %[[COORD:.*]] = shufflevector <4 x i32> %[[LOCATION_VAL]], <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
+// CHECK: %[[LOD:.*]] = extractelement <4 x i32> %[[LOCATION_VAL]], i64 3
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], <3 x i32> %[[COORD]], i32 %[[LOD]], <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], <3 x i32> %[[COORD]], i32 %[[LOD]], <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_load_offset(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Load(int vector[4], int vector[2])(ptr {{.*}} @t, <4 x i32> noundef %{{.*}}, <2 x i32> noundef splat (i32 1))
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_load_offset(int2 loc : LOC) : SV_Target {
+ return t.Load(int4(loc, 0, 0), int2(1, 1));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Load(int vector[4], int vector[2])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]], <2 x i32> {{.*}} %[[OFFSET:.*]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[LOCATION_ADDR:.*]] = alloca <4 x i32>
+// CHECK: %[[OFFSET_ADDR:.*]] = alloca <2 x i32>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <4 x i32> %[[LOCATION]], ptr %[[LOCATION_ADDR]]
+// CHECK: store <2 x i32> %[[OFFSET]], ptr %[[OFFSET_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target("{{(dx.Texture|spirv.Image)}}", {{.*}}), ptr %[[HANDLE_GEP]]
+// CHECK: %[[LOCATION_VAL:.*]] = load <4 x i32>, ptr %[[LOCATION_ADDR]]
+// CHECK: %[[COORD:.*]] = shufflevector <4 x i32> %[[LOCATION_VAL]], <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
+// CHECK: %[[LOD:.*]] = extractelement <4 x i32> %[[LOCATION_VAL]], i64 3
+// CHECK: %[[OFFSET_VAL:.*]] = load <2 x i32>, ptr %[[OFFSET_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], <3 x i32> %[[COORD]], i32 %[[LOD]], <2 x i32> %[[OFFSET_VAL]])
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], <3 x i32> %[[COORD]], i32 %[[LOD]], <2 x i32> %[[OFFSET_VAL]])
+// CHECK: ret <4 x float> %[[RES]]
+
+
+// For the rest of the types, we just check that the call to the member
+// function has the correct return type.
+
+Texture2DArray<float> t_float;
+
+// CHECK: define hidden {{.*}} float @test_load_float(int vector[2])
+// CHECK: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float>::Load(int vector[4])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]])
+// DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.resource.load.level.f32.tdx.Texture_f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", float, 0, 0, 0, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} float @llvm.spv.resource.load.level.f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// CHECK: ret float %[[RES]]
+float test_load_float(int2 loc : LOC) {
+ return t_float.Load(int4(loc, 0, 0));
+}
+
+// CHECK: define hidden {{.*}} float @test_load_offset_float(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} float @hlsl::Texture2DArray<float>::Load(int vector[4], int vector[2])(ptr {{.*}} @t_float, <4 x i32> noundef %{{.*}}, <2 x i32> noundef splat (i32 1))
+// CHECK: ret float %[[CALL]]
+float test_load_offset_float(int2 loc : LOC) {
+ return t_float.Load(int4(loc, 0, 0), int2(1, 1));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float>::Load(int vector[4], int vector[2])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]], <2 x i32> {{.*}} %[[OFFSET:.*]])
+// DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.resource.load.level.f32.tdx.Texture_f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", float, 0, 0, 0, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// SPIRV: %[[RES:.*]] = call {{.*}} float @llvm.spv.resource.load.level.f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// CHECK: ret float %[[RES]]
+
+Texture2DArray<float2> t_float2;
+
+// CHECK: define hidden {{.*}} <2 x float> @test_load_float2(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <2 x float> @hlsl::Texture2DArray<float vector[2]>::Load(int vector[4])(ptr {{.*}} @t_float2, <4 x i32> noundef %{{.*}})
+// CHECK: ret <2 x float> %[[CALL]]
+float2 test_load_float2(int2 loc : LOC) {
+ return t_float2.Load(int4(loc, 0, 0));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <2 x float> @hlsl::Texture2DArray<float vector[2]>::Load(int vector[4])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]])
+// DXIL: %[[RES:.*]] = call {{.*}} <2 x float> @llvm.dx.resource.load.level.v2f32.tdx.Texture_v2f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", <2 x float>, 0, 0, 0, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <2 x float> @llvm.spv.resource.load.level.v2f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// CHECK: ret <2 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <2 x float> @test_load_offset_float2(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <2 x float> @hlsl::Texture2DArray<float vector[2]>::Load(int vector[4], int vector[2])(ptr {{.*}} @t_float2, <4 x i32> noundef %{{.*}}, <2 x i32> noundef splat (i32 1))
+// CHECK: ret <2 x float> %[[CALL]]
+float2 test_load_offset_float2(int2 loc : LOC) {
+ return t_float2.Load(int4(loc, 0, 0), int2(1, 1));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <2 x float> @hlsl::Texture2DArray<float vector[2]>::Load(int vector[4], int vector[2])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]], <2 x i32> {{.*}} %[[OFFSET:.*]])
+// DXIL: %[[RES:.*]] = call {{.*}} <2 x float> @llvm.dx.resource.load.level.v2f32.tdx.Texture_v2f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", <2 x float>, 0, 0, 0, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// SPIRV: %[[RES:.*]] = call {{.*}} <2 x float> @llvm.spv.resource.load.level.v2f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// CHECK: ret <2 x float> %[[RES]]
+
+Texture2DArray<float3> t_float3;
+
+// CHECK: define hidden {{.*}} <3 x float> @test_load_float3(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <3 x float> @hlsl::Texture2DArray<float vector[3]>::Load(int vector[4])(ptr {{.*}} @t_float3, <4 x i32> noundef %{{.*}})
+// CHECK: ret <3 x float> %[[CALL]]
+float3 test_load_float3(int2 loc : LOC) {
+ return t_float3.Load(int4(loc, 0, 0));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <3 x float> @hlsl::Texture2DArray<float vector[3]>::Load(int vector[4])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]])
+// DXIL: %[[RES:.*]] = call {{.*}} <3 x float> @llvm.dx.resource.load.level.v3f32.tdx.Texture_v3f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", <3 x float>, 0, 0, 0, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <3 x float> @llvm.spv.resource.load.level.v3f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// CHECK: ret <3 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <3 x float> @test_load_offset_float3(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <3 x float> @hlsl::Texture2DArray<float vector[3]>::Load(int vector[4], int vector[2])(ptr {{.*}} @t_float3, <4 x i32> noundef %{{.*}}, <2 x i32> noundef splat (i32 1))
+// CHECK: ret <3 x float> %[[CALL]]
+float3 test_load_offset_float3(int2 loc : LOC) {
+ return t_float3.Load(int4(loc, 0, 0), int2(1, 1));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <3 x float> @hlsl::Texture2DArray<float vector[3]>::Load(int vector[4], int vector[2])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]], <2 x i32> {{.*}} %[[OFFSET:.*]])
+// DXIL: %[[RES:.*]] = call {{.*}} <3 x float> @llvm.dx.resource.load.level.v3f32.tdx.Texture_v3f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", <3 x float>, 0, 0, 0, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// SPIRV: %[[RES:.*]] = call {{.*}} <3 x float> @llvm.spv.resource.load.level.v3f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// CHECK: ret <3 x float> %[[RES]]
+
+Texture2DArray<int> t_int;
+
+// CHECK: define hidden {{.*}} i32 @test_load_int(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} i32 @hlsl::Texture2DArray<int>::Load(int vector[4])(ptr {{.*}} @t_int, <4 x i32> noundef %{{.*}})
+// CHECK: ret i32 %[[CALL]]
+int test_load_int(int2 loc : LOC) {
+ return t_int.Load(int4(loc, 0, 0));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} i32 @hlsl::Texture2DArray<int>::Load(int vector[4])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]])
+// DXIL: %[[RES:.*]] = call i32 @llvm.dx.resource.load.level.i32.tdx.Texture_i32_0_0_1_7t.v3i32.i32.v2i32(target("dx.Texture", i32, 0, 0, 1, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call i32 @llvm.spv.resource.load.level.i32.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// CHECK: ret i32 %[[RES]]
+
+// CHECK: define hidden {{.*}} i32 @test_load_offset_int(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} i32 @hlsl::Texture2DArray<int>::Load(int vector[4], int vector[2])(ptr {{.*}} @t_int, <4 x i32> noundef %{{.*}}, <2 x i32> noundef splat (i32 1))
+// CHECK: ret i32 %[[CALL]]
+int test_load_offset_int(int2 loc : LOC) {
+ return t_int.Load(int4(loc, 0, 0), int2(1, 1));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} i32 @hlsl::Texture2DArray<int>::Load(int vector[4], int vector[2])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]], <2 x i32> {{.*}} %[[OFFSET:.*]])
+// DXIL: %[[RES:.*]] = call i32 @llvm.dx.resource.load.level.i32.tdx.Texture_i32_0_0_1_7t.v3i32.i32.v2i32(target("dx.Texture", i32, 0, 0, 1, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// SPIRV: %[[RES:.*]] = call i32 @llvm.spv.resource.load.level.i32.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// CHECK: ret i32 %[[RES]]
+
+Texture2DArray<int2> t_int2;
+
+// CHECK: define hidden {{.*}} <2 x i32> @test_load_int2(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <2 x i32> @hlsl::Texture2DArray<int vector[2]>::Load(int vector[4])(ptr {{.*}} @t_int2, <4 x i32> noundef %{{.*}})
+// CHECK: ret <2 x i32> %[[CALL]]
+int2 test_load_int2(int2 loc : LOC) {
+ return t_int2.Load(int4(loc, 0, 0));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <2 x i32> @hlsl::Texture2DArray<int vector[2]>::Load(int vector[4])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]])
+// DXIL: %[[RES:.*]] = call <2 x i32> @llvm.dx.resource.load.level.v2i32.tdx.Texture_v2i32_0_0_1_7t.v3i32.i32.v2i32(target("dx.Texture", <2 x i32>, 0, 0, 1, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call <2 x i32> @llvm.spv.resource.load.level.v2i32.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// CHECK: ret <2 x i32> %[[RES]]
+
+// CHECK: define hidden {{.*}} <2 x i32> @test_load_offset_int2(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <2 x i32> @hlsl::Texture2DArray<int vector[2]>::Load(int vector[4], int vector[2])(ptr {{.*}} @t_int2, <4 x i32> noundef %{{.*}}, <2 x i32> noundef splat (i32 1))
+// CHECK: ret <2 x i32> %[[CALL]]
+int2 test_load_offset_int2(int2 loc : LOC) {
+ return t_int2.Load(int4(loc, 0, 0), int2(1, 1));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <2 x i32> @hlsl::Texture2DArray<int vector[2]>::Load(int vector[4], int vector[2])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]], <2 x i32> {{.*}} %[[OFFSET:.*]])
+// DXIL: %[[RES:.*]] = call <2 x i32> @llvm.dx.resource.load.level.v2i32.tdx.Texture_v2i32_0_0_1_7t.v3i32.i32.v2i32(target("dx.Texture", <2 x i32>, 0, 0, 1, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// SPIRV: %[[RES:.*]] = call <2 x i32> @llvm.spv.resource.load.level.v2i32.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// CHECK: ret <2 x i32> %[[RES]]
+
+Texture2DArray<int3> t_int3;
+
+// CHECK: define hidden {{.*}} <3 x i32> @test_load_int3(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <3 x i32> @hlsl::Texture2DArray<int vector[3]>::Load(int vector[4])(ptr {{.*}} @t_int3, <4 x i32> noundef %{{.*}})
+// CHECK: ret <3 x i32> %[[CALL]]
+int3 test_load_int3(int2 loc : LOC) {
+ return t_int3.Load(int4(loc, 0, 0));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <3 x i32> @hlsl::Texture2DArray<int vector[3]>::Load(int vector[4])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]])
+// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.load.level.v3i32.tdx.Texture_v3i32_0_0_1_7t.v3i32.i32.v2i32(target("dx.Texture", <3 x i32>, 0, 0, 1, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.load.level.v3i32.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// CHECK: ret <3 x i32> %[[RES]]
+
+// CHECK: define hidden {{.*}} <3 x i32> @test_load_offset_int3(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <3 x i32> @hlsl::Texture2DArray<int vector[3]>::Load(int vector[4], int vector[2])(ptr {{.*}} @t_int3, <4 x i32> noundef %{{.*}}, <2 x i32> noundef splat (i32 1))
+// CHECK: ret <3 x i32> %[[CALL]]
+int3 test_load_offset_int3(int2 loc : LOC) {
+ return t_int3.Load(int4(loc, 0, 0), int2(1, 1));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <3 x i32> @hlsl::Texture2DArray<int vector[3]>::Load(int vector[4], int vector[2])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]], <2 x i32> {{.*}} %[[OFFSET:.*]])
+// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.load.level.v3i32.tdx.Texture_v3i32_0_0_1_7t.v3i32.i32.v2i32(target("dx.Texture", <3 x i32>, 0, 0, 1, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.load.level.v3i32.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// CHECK: ret <3 x i32> %[[RES]]
+
+Texture2DArray<int4> t_int4;
+
+// CHECK: define hidden {{.*}} <4 x i32> @test_load_int4(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x i32> @hlsl::Texture2DArray<int vector[4]>::Load(int vector[4])(ptr {{.*}} @t_int4, <4 x i32> noundef %{{.*}})
+// CHECK: ret <4 x i32> %[[CALL]]
+int4 test_load_int4(int2 loc : LOC) {
+ return t_int4.Load(int4(loc, 0, 0));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x i32> @hlsl::Texture2DArray<int vector[4]>::Load(int vector[4])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]])
+// DXIL: %[[RES:.*]] = call <4 x i32> @llvm.dx.resource.load.level.v4i32.tdx.Texture_v4i32_0_0_1_7t.v3i32.i32.v2i32(target("dx.Texture", <4 x i32>, 0, 0, 1, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call <4 x i32> @llvm.spv.resource.load.level.v4i32.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> zeroinitializer)
+// CHECK: ret <4 x i32> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x i32> @test_load_offset_int4(int vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x i32> @hlsl::Texture2DArray<int vector[4]>::Load(int vector[4], int vector[2])(ptr {{.*}} @t_int4, <4 x i32> noundef %{{.*}}, <2 x i32> noundef splat (i32 1))
+// CHECK: ret <4 x i32> %[[CALL]]
+int4 test_load_offset_int4(int2 loc : LOC) {
+ return t_int4.Load(int4(loc, 0, 0), int2(1, 1));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x i32> @hlsl::Texture2DArray<int vector[4]>::Load(int vector[4], int vector[2])(ptr {{.*}} %[[THIS:.*]], <4 x i32> {{.*}} %[[LOCATION:.*]], <2 x i32> {{.*}} %[[OFFSET:.*]])
+// DXIL: %[[RES:.*]] = call <4 x i32> @llvm.dx.resource.load.level.v4i32.tdx.Texture_v4i32_0_0_1_7t.v3i32.i32.v2i32(target("dx.Texture", <4 x i32>, 0, 0, 1, 7) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// SPIRV: %[[RES:.*]] = call <4 x i32> @llvm.spv.resource.load.level.v4i32.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %{{.*}}, <3 x i32> %{{.*}}, i32 %{{.*}}, <2 x i32> %{{.*}})
+// CHECK: ret <4 x i32> %[[RES]]
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-Mips.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-Mips.hlsl
new file mode 100644
index 0000000000000..f42963165e7c2
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-Mips.hlsl
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+
+Texture2DArray<float4> t;
+
+// CHECK: define internal {{.*}} <4 x float> @test_mips(float vector[3])(<3 x float> {{.*}} %loc)
+// CHECK: entry:
+// CHECK: %[[LOC_ADDR:.*]] = alloca <3 x float>
+// CHECK: %[[REF_TMP:.*]] = alloca %"struct.hlsl::Texture2DArray<>::mips_slice_type"
+// CHECK: store <3 x float> %loc, ptr %[[LOC_ADDR]]
+// CHECK: call void @hlsl::Texture2DArray<float vector[4]>::mips_type::operator[](int) const(ptr {{.*}} %[[REF_TMP]], ptr {{.*}} getelementptr {{.*}} (i8, ptr @t, i32 4), i32 noundef 0)
+// CHECK: %[[V0:.*]] = load <3 x float>, ptr %[[LOC_ADDR]]
+// CHECK: %[[SHUF:.*]] = shufflevector <3 x float> %[[V0]], <3 x float> poison, <2 x i32> <i32 0, i32 1>
+// CHECK: %[[CONV:.*]] = fptosi <2 x float> %[[SHUF]] to <2 x i32>
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::mips_slice_type::operator[](int vector[3]) const(ptr {{.*}} %[[REF_TMP]], <3 x i32> {{.*}} %[[VEC:.*]])
+// CHECK: ret <4 x float> %[[CALL]]
+
+[shader("pixel")]
+float4 test_mips(float3 loc : LOC) : SV_Target {
+ return t.mips[0][int3(int2(loc.xy), 0)];
+}
+
+// CHECK: define linkonce_odr hidden void @hlsl::Texture2DArray<float vector[4]>::mips_type::operator[](int) const(ptr {{.*}} %agg.result, ptr {{.*}} %this, i32 {{.*}} %Level)
+// CHECK: entry:
+// CHECK: %{{.*}} = alloca ptr
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[LEVEL_ADDR:.*]] = alloca i32
+// CHECK: %[[SLICE:.*]] = alloca %"struct.hlsl::Texture2DArray<>::mips_slice_type"
+// CHECK: store ptr %agg.result, ptr %{{.*}}
+// CHECK: store ptr %this, ptr %[[THIS_ADDR]]
+// CHECK: store i32 %Level, ptr %[[LEVEL_ADDR]]
+// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: call void @hlsl::Texture2DArray<float vector[4]>::mips_slice_type::mips_slice_type()(ptr {{.*}} %[[SLICE]])
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2DArray<>::mips_type", ptr %[[THIS1]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 7), ptr %[[HANDLE_GEP]]
+// CHECK: %[[HANDLE_GEP2:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2DArray<>::mips_slice_type", ptr %[[SLICE]], i32 0, i32 0
+// CHECK: store target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], ptr %[[HANDLE_GEP2]]
+// CHECK: %[[L_VAL:.*]] = load i32, ptr %[[LEVEL_ADDR]]
+// CHECK: %[[LEVEL_GEP:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2DArray<>::mips_slice_type", ptr %[[SLICE]], i32 0, i32 1
+// CHECK: store i32 %[[L_VAL]], ptr %[[LEVEL_GEP]]
+// CHECK: call void @hlsl::Texture2DArray<float vector[4]>::mips_slice_type::mips_slice_type(hlsl::Texture2DArray<float vector[4]>::mips_slice_type const&)(ptr noundef nonnull align 4 dereferenceable(8) %agg.result, ptr noundef nonnull align 4 dereferenceable(8) %[[SLICE]])
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::mips_slice_type::operator[](int vector[3]) const(ptr {{.*}} %[[THIS:.*]], <3 x i32> noundef %[[COORD:.*]])
+// CHECK: entry:
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x i32>
+// CHECK: %[[VEC_TMP:.*]] = alloca <3 x i32>
+// CHECK: store <3 x i32> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: %[[THIS1:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[COORD_PARAM:.*]] = load <3 x i32>, ptr %[[COORD_ADDR]]
+// CHECK: store <3 x i32> %[[COORD_PARAM]], ptr %[[VEC_TMP]]
+// CHECK: %[[HANDLE_PTR:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2DArray<>::mips_slice_type", ptr %[[THIS1]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 7), ptr %[[HANDLE_PTR]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x i32>, ptr %[[VEC_TMP]]
+// CHECK: %[[VECEXT:.*]] = extractelement <3 x i32> %[[COORD_VAL]], i32 0
+// CHECK: %[[VECINIT:.*]] = insertelement <4 x i32> poison, i32 %[[VECEXT]], i32 0
+// CHECK: %[[COORD_VAL2:.*]] = load <3 x i32>, ptr %[[VEC_TMP]]
+// CHECK: %[[VECEXT2:.*]] = extractelement <3 x i32> %[[COORD_VAL2]], i32 1
+// CHECK: %[[VECINIT3:.*]] = insertelement <4 x i32> %[[VECINIT]], i32 %[[VECEXT2]], i32 1
+// CHECK: %[[COORD_VAL3:.*]] = load <3 x i32>, ptr %[[VEC_TMP]]
+// CHECK: %[[VECEXT3:.*]] = extractelement <3 x i32> %[[COORD_VAL3]], i32 2
+// CHECK: %[[VECINIT4:.*]] = insertelement <4 x i32> %[[VECINIT3]], i32 %[[VECEXT3]], i32 2
+// CHECK: %[[LEVEL_PTR:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2DArray<>::mips_slice_type", ptr %[[THIS1]], i32 0, i32 1
+// CHECK: %[[LEVEL_VAL:.*]] = load i32, ptr %[[LEVEL_PTR]]
+// CHECK: %[[VECINIT5:.*]] = insertelement <4 x i32> %[[VECINIT4]], i32 %[[LEVEL_VAL]], i32 3
+// CHECK: %[[COORD_X:.*]] = shufflevector <4 x i32> %[[VECINIT5]], <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
+// CHECK: %[[LOD:.*]] = extractelement <4 x i32> %[[VECINIT5]], i64 3
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_7t.v3i32.i32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], <3 x i32> %[[COORD_X]], i32 %[[LOD]], <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-Sample.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-Sample.hlsl
new file mode 100644
index 0000000000000..7f875e6010fa5
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-Sample.hlsl
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+// DXIL: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) }
+
+// SPIRV: %"class.hlsl::Texture2DArray" = type { target("spirv.Image", float, 1, 2, 1, 0, 1, 0), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") }
+
+Texture2DArray<float4> t;
+SamplerState s;
+
+// CHECK: define hidden {{.*}} <4 x float> @main(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}})
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 main(float3 loc : LOC) : SV_Target {
+ return t.Sample(s, loc);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.sample.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], <2 x i32> zeroinitializer)
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.sample.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], <2 x i32> zeroinitializer)
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_offset(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3], int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, <2 x i32> {{.*}} <i32 1, i32 2>)
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_offset(float3 loc : LOC) : SV_Target {
+ return t.Sample(s, loc, int2(1, 2));
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3], int vector[2])(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^,]+]], <2 x i32> {{.*}} %[[OFFSET:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: %[[OFFSET_ADDR:.*]] = alloca <2 x i32>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: store <2 x i32> %[[OFFSET]], ptr %[[OFFSET_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// CHECK: %[[OFFSET_VAL:.*]] = load <2 x i32>, ptr %[[OFFSET_ADDR]]
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.sample.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], <2 x i32> %[[OFFSET_VAL]])
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.sample.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], <2 x i32> %[[OFFSET_VAL]])
+// CHECK: ret <4 x float> %[[RES]]
+
+// CHECK: define hidden {{.*}} <4 x float> @test_clamp(float vector[3])(<3 x float> noundef nofpclass(nan inf) %[[LOC:.*]])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3], int vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}}, <2 x i32> {{.*}} <i32 1, i32 2>, float {{.*}} 1.000000e+00)
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_clamp(float3 loc : LOC) : SV_Target {
+ return t.Sample(s, loc, int2(1, 2), 1.0f);
+}
+
+// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3], int vector[2], float)(ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^,]+]], <2 x i32> {{.*}} %[[OFFSET:[^,]+]], float {{.*}} %[[CLAMP:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: %[[OFFSET_ADDR:.*]] = alloca <2 x i32>
+// CHECK: %[[CLAMP_ADDR:.*]] = alloca float
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: store <2 x i32> %[[OFFSET]], ptr %[[OFFSET_ADDR]]
+// CHECK: store float %[[CLAMP]], ptr %[[CLAMP_ADDR]]
+// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL]], i32 0, i32 0
+// CHECK: %[[HANDLE:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP]]
+// CHECK: %[[SAMPLER_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// CHECK: %[[OFFSET_VAL:.*]] = load <2 x i32>, ptr %[[OFFSET_ADDR]]
+// CHECK: %[[CLAMP_VAL:.*]] = load float, ptr %[[CLAMP_ADDR]]
+// CHECK: %[[CLAMP_CAST:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.sample.clamp.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], target("dx.Sampler", 0) %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], <2 x i32> %[[OFFSET_VAL]], float %[[CLAMP_CAST]])
+// SPIRV: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.spv.resource.sample.clamp.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], target("spirv.Sampler") %[[SAMPLER_H]], <3 x float> %[[COORD_VAL]], <2 x i32> %[[OFFSET_VAL]], float %[[CLAMP_CAST]])
+// CHECK: ret <4 x float> %[[RES]]
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleBias.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleBias.hlsl
new file mode 100644
index 0000000000000..cf27cde829cc5
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleBias.hlsl
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+// DXIL: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) }
+
+// SPIRV: %"class.hlsl::Texture2DArray" = type { target("spirv.Image", float, 1, 2, 1, 0, 1, 0), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") }
+
+Texture2DArray<float4> t;
+SamplerState s;
+
+// CHECK-LABEL: @test_bias(float vector[3])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[3], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00)
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_bias(float3 loc : LOC) : SV_Target {
+ return t.SampleBias(s, loc, 0.0f);
+}
+
+// CHECK-LABEL: define linkonce_odr {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[3], float)(
+// CHECK: %[[THIS_VAL1:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[HANDLE_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL1]], i32 0, i32 0
+// CHECK: %[[HANDLE1:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP1]]
+// CHECK: %[[SAMPLER_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %{{.*}}, i32 0, i32 0
+// CHECK: %[[SAMPLER_H1:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP1]]
+// CHECK: %[[BIAS_CAST1:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: %{{.*}} = call {{.*}} <4 x float> @llvm.dx.resource.samplebias.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <3 x float> %{{.*}}, float %[[BIAS_CAST1]], <2 x i32> zeroinitializer)
+// SPIRV: %{{.*}} = call {{.*}} <4 x float> @llvm.spv.resource.samplebias.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <3 x float> %{{.*}}, float %[[BIAS_CAST1]], <2 x i32> zeroinitializer)
+
+// CHECK-LABEL: @test_offset(float vector[3])
+// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[3], float, int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>)
+// CHECK: ret <4 x float> %[[CALL_OFFSET]]
+
+float4 test_offset(float3 loc : LOC) : SV_Target {
+ return t.SampleBias(s, loc, 0.0f, int2(1, 2));
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[3], float, int vector[2])(
+// CHECK: %[[THIS_VAL2:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[HANDLE_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL2]], i32 0, i32 0
+// CHECK: %[[HANDLE2:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP2]]
+// CHECK: %[[SAMPLER_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %{{.*}}, i32 0, i32 0
+// CHECK: %[[SAMPLER_H2:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP2]]
+// CHECK: %[[BIAS_CAST2:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: %{{.*}} = call {{.*}} <4 x float> @llvm.dx.resource.samplebias.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <3 x float> %{{.*}}, float %[[BIAS_CAST2]], <2 x i32> %{{.*}})
+// SPIRV: %{{.*}} = call {{.*}} <4 x float> @llvm.spv.resource.samplebias.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <3 x float> %{{.*}}, float %[[BIAS_CAST2]], <2 x i32> %{{.*}})
+
+// CHECK-LABEL: @test_clamp(float vector[3])
+// CHECK: %[[CALL_CLAMP:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[3], float, int vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>, float {{.*}} 1.000000e+00)
+// CHECK: ret <4 x float> %[[CALL_CLAMP]]
+
+float4 test_clamp(float3 loc : LOC) : SV_Target {
+ return t.SampleBias(s, loc, 0.0f, int2(1, 2), 1.0f);
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[3], float, int vector[2], float)(
+// CHECK: %[[THIS_VAL3:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[HANDLE_GEP3:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL3]], i32 0, i32 0
+// CHECK: %[[HANDLE3:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP3]]
+// CHECK: %[[SAMPLER_GEP3:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %{{.*}}, i32 0, i32 0
+// CHECK: %[[SAMPLER_H3:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP3]]
+// CHECK: %[[BIAS_CAST3:.*]] = fptrunc {{.*}} double {{.*}} to float
+// CHECK: %[[CLAMP_CAST3:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: %{{.*}} = call {{.*}} <4 x float> @llvm.dx.resource.samplebias.clamp.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE3]], target("dx.Sampler", 0) %[[SAMPLER_H3]], <3 x float> %{{.*}}, float %[[BIAS_CAST3]], <2 x i32> %{{.*}}, float %[[CLAMP_CAST3]])
+// SPIRV: %{{.*}} = call {{.*}} <4 x float> @llvm.spv.resource.samplebias.clamp.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE3]], target("spirv.Sampler") %[[SAMPLER_H3]], <3 x float> %{{.*}}, float %[[BIAS_CAST3]], <2 x i32> %{{.*}}, float %[[CLAMP_CAST3]])
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleCmp.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleCmp.hlsl
new file mode 100644
index 0000000000000..ff0da74489e92
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleCmp.hlsl
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+// DXIL: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// DXIL: %"class.hlsl::SamplerComparisonState" = type { target("dx.Sampler", 0) }
+
+// SPIRV: %"class.hlsl::Texture2DArray" = type { target("spirv.Image", float, 1, 2, 1, 0, 1, 0), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// SPIRV: %"class.hlsl::SamplerComparisonState" = type { target("spirv.Sampler") }
+
+Texture2DArray<float4> t;
+SamplerComparisonState s;
+
+// CHECK-LABEL: @test_cmp(float vector[3], float)
+// CHECK: %[[CALL:.*]] = call {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[3], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00)
+// CHECK: ret float %[[CALL]]
+
+float test_cmp(float3 loc : LOC, float cmp : CMP) : SV_Target {
+ return t.SampleCmp(s, loc, 0.0f);
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[3], float)(
+// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS1:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER1:[^,]+]], <3 x float> noundef nofpclass(nan inf) %[[COORD1:[^,]+]], float noundef nofpclass(nan inf) %[[CMP1:[^)]+]])
+// CHECK: %[[THIS_VAL1:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[HANDLE_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL1]], i32 0, i32 0
+// CHECK: %[[HANDLE1:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP1]]
+// CHECK: %[[SAMPLER_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerComparisonState", ptr %[[SAMPLER1]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H1:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP1]]
+// CHECK: %[[COORD_VAL1:.*]] = load <3 x float>, ptr %{{.*}}
+// CHECK: %[[CMP_VAL1:.*]] = load float, ptr %{{.*}}
+// CHECK: %[[CMP_CAST1:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: call {{.*}} float @llvm.dx.resource.samplecmp.f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <3 x float> %[[COORD_VAL1]], float %[[CMP_CAST1]], <2 x i32> zeroinitializer)
+// SPIRV: call {{.*}} float @llvm.spv.resource.samplecmp.f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <3 x float> %[[COORD_VAL1]], float %[[CMP_CAST1]], <2 x i32> zeroinitializer)
+
+// CHECK-LABEL: @test_offset(float vector[3], float)
+// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[3], float, int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>)
+// CHECK: ret float %[[CALL_OFFSET]]
+
+float test_offset(float3 loc : LOC, float cmp : CMP) : SV_Target {
+ return t.SampleCmp(s, loc, 0.0f, int2(1, 2));
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[3], float, int vector[2])(
+// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS2:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER2:[^,]+]], <3 x float> noundef nofpclass(nan inf) %[[COORD2:[^,]+]], float noundef nofpclass(nan inf) %[[CMP2:[^,]+]], <2 x i32> noundef %[[OFFSET2:[^)]+]])
+// CHECK: %[[THIS_VAL2:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[HANDLE_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL2]], i32 0, i32 0
+// CHECK: %[[HANDLE2:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP2]]
+// CHECK: %[[SAMPLER_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerComparisonState", ptr %[[SAMPLER2]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H2:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP2]]
+// CHECK: %[[COORD_VAL2:.*]] = load <3 x float>, ptr %{{.*}}
+// CHECK: %[[CMP_VAL2:.*]] = load float, ptr %{{.*}}
+// CHECK: %[[CMP_CAST2:.*]] = fptrunc {{.*}} double {{.*}} to float
+// CHECK: %[[OFFSET_VAL2:.*]] = load <2 x i32>, ptr %{{.*}}
+// DXIL: call {{.*}} float @llvm.dx.resource.samplecmp.f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <3 x float> %[[COORD_VAL2]], float %[[CMP_CAST2]], <2 x i32> %[[OFFSET_VAL2]])
+// SPIRV: call {{.*}} float @llvm.spv.resource.samplecmp.f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <3 x float> %[[COORD_VAL2]], float %[[CMP_CAST2]], <2 x i32> %[[OFFSET_VAL2]])
+
+// CHECK-LABEL: @test_clamp(float vector[3], float)
+// CHECK: %[[CALL_CLAMP:.*]] = call {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[3], float, int vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>, float {{.*}} 1.000000e+00)
+// CHECK: ret float %[[CALL_CLAMP]]
+
+float test_clamp(float3 loc : LOC, float cmp : CMP) : SV_Target {
+ return t.SampleCmp(s, loc, 0.0f, int2(1, 2), 1.0f);
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[3], float, int vector[2], float)(
+// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS3:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER3:[^,]+]], <3 x float> noundef nofpclass(nan inf) %[[COORD3:[^,]+]], float noundef nofpclass(nan inf) %[[CMP3:[^,]+]], <2 x i32> noundef %[[OFFSET3:[^,]+]], float noundef nofpclass(nan inf) %[[CLAMP3:[^)]+]])
+// CHECK: %[[THIS_VAL3:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[HANDLE_GEP3:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL3]], i32 0, i32 0
+// CHECK: %[[HANDLE3:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP3]]
+// CHECK: %[[SAMPLER_GEP3:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerComparisonState", ptr %[[SAMPLER3]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H3:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP3]]
+// CHECK: %[[COORD_VAL3:.*]] = load <3 x float>, ptr %{{.*}}
+// CHECK: %[[CMP_VAL3:.*]] = load float, ptr %{{.*}}
+// CHECK: %[[CMP_CAST3:.*]] = fptrunc {{.*}} double {{.*}} to float
+// CHECK: %[[OFFSET_VAL3:.*]] = load <2 x i32>, ptr %{{.*}}
+// CHECK: %[[CLAMP_VAL3:.*]] = load float, ptr %{{.*}}
+// CHECK: %[[CLAMP_CAST3:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: call {{.*}} float @llvm.dx.resource.samplecmp.clamp.f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE3]], target("dx.Sampler", 0) %[[SAMPLER_H3]], <3 x float> %[[COORD_VAL3]], float %[[CMP_CAST3]], <2 x i32> %[[OFFSET_VAL3]], float %[[CLAMP_CAST3]])
+// SPIRV: call {{.*}} float @llvm.spv.resource.samplecmp.clamp.f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE3]], target("spirv.Sampler") %[[SAMPLER_H3]], <3 x float> %[[COORD_VAL3]], float %[[CMP_CAST3]], <2 x i32> %[[OFFSET_VAL3]], float %[[CLAMP_CAST3]])
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleCmpLevelZero.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleCmpLevelZero.hlsl
new file mode 100644
index 0000000000000..06916a9b2e357
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleCmpLevelZero.hlsl
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+Texture2DArray<float4> t;
+SamplerComparisonState s;
+
+// CHECK-LABEL: @test_cmp_level_zero(float vector[3], float)
+// CHECK: %[[CALL:.*]] = call {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmpLevelZero(hlsl::SamplerComparisonState, float vector[3], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00)
+// CHECK: ret float %[[CALL]]
+
+float test_cmp_level_zero(float3 loc : LOC, float cmp : CMP) : SV_Target {
+ return t.SampleCmpLevelZero(s, loc, 0.0f);
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmpLevelZero(hlsl::SamplerComparisonState, float vector[3], float)(
+// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS1:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER1:[^,]+]], <3 x float> noundef nofpclass(nan inf) %[[COORD1:[^,]+]], float noundef nofpclass(nan inf) %[[CMP1:[^)]+]])
+// CHECK: %[[THIS_VAL1:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[HANDLE_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL1]], i32 0, i32 0
+// CHECK: %[[HANDLE1:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP1]]
+// CHECK: %[[SAMPLER_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerComparisonState", ptr %[[SAMPLER1]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H1:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP1]]
+// CHECK: %[[COORD_VAL1:.*]] = load <3 x float>, ptr %{{.*}}
+// CHECK: %[[CMP_VAL1:.*]] = load float, ptr %{{.*}}
+// CHECK: %[[CMP_CAST1:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: call {{.*}} float @llvm.dx.resource.samplecmplevelzero.f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <3 x float> %[[COORD_VAL1]], float %[[CMP_CAST1]], <2 x i32> zeroinitializer)
+// SPIRV: call {{.*}} float @llvm.spv.resource.samplecmplevelzero.f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <3 x float> %[[COORD_VAL1]], float %[[CMP_CAST1]], <2 x i32> zeroinitializer)
+
+// CHECK-LABEL: @test_cmp_level_zero_offset(float vector[3], float)
+// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmpLevelZero(hlsl::SamplerComparisonState, float vector[3], float, int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>)
+// CHECK: ret float %[[CALL_OFFSET]]
+
+float test_cmp_level_zero_offset(float3 loc : LOC, float cmp : CMP) : SV_Target {
+ return t.SampleCmpLevelZero(s, loc, 0.0f, int2(1, 2));
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} float @hlsl::Texture2DArray<float vector[4]>::SampleCmpLevelZero(hlsl::SamplerComparisonState, float vector[3], float, int vector[2])(
+// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS2:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER2:[^,]+]], <3 x float> noundef nofpclass(nan inf) %[[COORD2:[^,]+]], float noundef nofpclass(nan inf) %[[CMP2:[^,]+]], <2 x i32> noundef %[[OFFSET2:[^)]+]])
+// CHECK: %[[THIS_VAL2:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[HANDLE_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL2]], i32 0, i32 0
+// CHECK: %[[HANDLE2:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP2]]
+// CHECK: %[[SAMPLER_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerComparisonState", ptr %[[SAMPLER2]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H2:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP2]]
+// CHECK: %[[COORD_VAL2:.*]] = load <3 x float>, ptr %{{.*}}
+// CHECK: %[[CMP_VAL2:.*]] = load float, ptr %{{.*}}
+// CHECK: %[[CMP_CAST2:.*]] = fptrunc {{.*}} double {{.*}} to float
+// CHECK: %[[OFFSET_VAL2:.*]] = load <2 x i32>, ptr %{{.*}}
+// DXIL: call {{.*}} float @llvm.dx.resource.samplecmplevelzero.f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <3 x float> %[[COORD_VAL2]], float %[[CMP_CAST2]], <2 x i32> %[[OFFSET_VAL2]])
+// SPIRV: call {{.*}} float @llvm.spv.resource.samplecmplevelzero.f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <3 x float> %[[COORD_VAL2]], float %[[CMP_CAST2]], <2 x i32> %[[OFFSET_VAL2]])
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleGrad.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleGrad.hlsl
new file mode 100644
index 0000000000000..236d717120798
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleGrad.hlsl
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+// DXIL: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) }
+
+// SPIRV: %"class.hlsl::Texture2DArray" = type { target("spirv.Image", float, 1, 2, 1, 0, 1, 0), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") }
+
+Texture2DArray<float4> t;
+SamplerState s;
+
+// CHECK-LABEL: @test_grad(float vector[3], float vector[2], float vector[2])
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[3], float vector[2], float vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, <2 x float> {{.*}} %{{.*}}, <2 x float> {{.*}} %{{.*}})
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_grad(float3 loc : LOC, float2 ddx : DDX, float2 ddy : DDY) : SV_Target {
+ return t.SampleGrad(s, loc, ddx, ddy);
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[3], float vector[2], float vector[2])(
+// CHECK-SAME: ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^,]+]], <2 x float> {{.*}} %[[DDX:[^,]+]], <2 x float> {{.*}} %[[DDY:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: %[[DDX_ADDR:.*]] = alloca <2 x float>
+// CHECK: %[[DDY_ADDR:.*]] = alloca <2 x float>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: store <2 x float> %[[DDX]], ptr %[[DDX_ADDR]]
+// CHECK: store <2 x float> %[[DDY]], ptr %[[DDY_ADDR]]
+// CHECK: %[[THIS_VAL1:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL1]], i32 0, i32 0
+// CHECK: %[[HANDLE1:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP1]]
+// CHECK: %[[SAMPLER_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H1:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP1]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// CHECK: %[[DDX_VAL:.*]] = load <2 x float>, ptr %[[DDX_ADDR]]
+// CHECK: %[[DDY_VAL:.*]] = load <2 x float>, ptr %[[DDY_ADDR]]
+// DXIL: call {{.*}} <4 x float> @llvm.dx.resource.samplegrad.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2f32.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <3 x float> %[[COORD_VAL]], <2 x float> %[[DDX_VAL]], <2 x float> %[[DDY_VAL]], <2 x i32> zeroinitializer)
+// SPIRV: call {{.*}} <4 x float> @llvm.spv.resource.samplegrad.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <3 x float> %[[COORD_VAL]], <2 x float> %[[DDX_VAL]], <2 x float> %[[DDY_VAL]], <2 x i32> zeroinitializer)
+
+// CHECK-LABEL: @test_offset(float vector[3], float vector[2], float vector[2])
+// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[3], float vector[2], float vector[2], int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, <2 x float> {{.*}} %{{.*}}, <2 x float> {{.*}} %{{.*}}, <2 x i32> noundef <i32 1, i32 2>)
+// CHECK: ret <4 x float> %[[CALL_OFFSET]]
+
+float4 test_offset(float3 loc : LOC, float2 ddx : DDX, float2 ddy : DDY) : SV_Target {
+ return t.SampleGrad(s, loc, ddx, ddy, int2(1, 2));
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[3], float vector[2], float vector[2], int vector[2])(
+// CHECK-SAME: ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^,]+]], <2 x float> {{.*}} %[[DDX:[^,]+]], <2 x float> {{.*}} %[[DDY:[^,]+]], <2 x i32> {{.*}} %[[OFFSET:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: %[[DDX_ADDR:.*]] = alloca <2 x float>
+// CHECK: %[[DDY_ADDR:.*]] = alloca <2 x float>
+// CHECK: %[[OFFSET_ADDR:.*]] = alloca <2 x i32>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: store <2 x float> %[[DDX]], ptr %[[DDX_ADDR]]
+// CHECK: store <2 x float> %[[DDY]], ptr %[[DDY_ADDR]]
+// CHECK: store <2 x i32> %[[OFFSET]], ptr %[[OFFSET_ADDR]]
+// CHECK: %[[THIS_VAL2:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL2]], i32 0, i32 0
+// CHECK: %[[HANDLE2:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP2]]
+// CHECK: %[[SAMPLER_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H2:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP2]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// CHECK: %[[DDX_VAL:.*]] = load <2 x float>, ptr %[[DDX_ADDR]]
+// CHECK: %[[DDY_VAL:.*]] = load <2 x float>, ptr %[[DDY_ADDR]]
+// CHECK: %[[OFFSET_VAL:.*]] = load <2 x i32>, ptr %[[OFFSET_ADDR]]
+// DXIL: call {{.*}} <4 x float> @llvm.dx.resource.samplegrad.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2f32.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <3 x float> %[[COORD_VAL]], <2 x float> %[[DDX_VAL]], <2 x float> %[[DDY_VAL]], <2 x i32> %[[OFFSET_VAL]])
+// SPIRV: call {{.*}} <4 x float> @llvm.spv.resource.samplegrad.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <3 x float> %[[COORD_VAL]], <2 x float> %[[DDX_VAL]], <2 x float> %[[DDY_VAL]], <2 x i32> %[[OFFSET_VAL]])
+
+// CHECK-LABEL: @test_clamp(float vector[3], float vector[2], float vector[2])
+// CHECK: %[[CALL_CLAMP:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[3], float vector[2], float vector[2], int vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, <2 x float> {{.*}} %{{.*}}, <2 x float> {{.*}} %{{.*}}, <2 x i32> noundef <i32 1, i32 2>, float {{.*}} 1.000000e+00)
+// CHECK: ret <4 x float> %[[CALL_CLAMP]]
+
+float4 test_clamp(float3 loc : LOC, float2 ddx : DDX, float2 ddy : DDY) : SV_Target {
+ return t.SampleGrad(s, loc, ddx, ddy, int2(1, 2), 1.0f);
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[3], float vector[2], float vector[2], int vector[2], float)(
+// CHECK-SAME: ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <3 x float> {{.*}} %[[COORD:[^,]+]], <2 x float> {{.*}} %[[DDX:[^,]+]], <2 x float> {{.*}} %[[DDY:[^,]+]], <2 x i32> {{.*}} %[[OFFSET:[^,]+]], float {{.*}} %[[CLAMP:[^)]+]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR:.*]] = alloca <3 x float>
+// CHECK: %[[DDX_ADDR:.*]] = alloca <2 x float>
+// CHECK: %[[DDY_ADDR:.*]] = alloca <2 x float>
+// CHECK: %[[OFFSET_ADDR:.*]] = alloca <2 x i32>
+// CHECK: %[[CLAMP_ADDR:.*]] = alloca float
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x float> %[[COORD]], ptr %[[COORD_ADDR]]
+// CHECK: store <2 x float> %[[DDX]], ptr %[[DDX_ADDR]]
+// CHECK: store <2 x float> %[[DDY]], ptr %[[DDY_ADDR]]
+// CHECK: store <2 x i32> %[[OFFSET]], ptr %[[OFFSET_ADDR]]
+// CHECK: store float %[[CLAMP]], ptr %[[CLAMP_ADDR]]
+// CHECK: %[[THIS_VAL3:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_GEP3:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL3]], i32 0, i32 0
+// CHECK: %[[HANDLE3:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP3]]
+// CHECK: %[[SAMPLER_GEP3:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H3:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP3]]
+// CHECK: %[[COORD_VAL:.*]] = load <3 x float>, ptr %[[COORD_ADDR]]
+// CHECK: %[[DDX_VAL:.*]] = load <2 x float>, ptr %[[DDX_ADDR]]
+// CHECK: %[[DDY_VAL:.*]] = load <2 x float>, ptr %[[DDY_ADDR]]
+// CHECK: %[[OFFSET_VAL:.*]] = load <2 x i32>, ptr %[[OFFSET_ADDR]]
+// CHECK: %[[CLAMP_VAL:.*]] = load float, ptr %[[CLAMP_ADDR]]
+// CHECK: %[[CLAMP_CAST3:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: call {{.*}} <4 x float> @llvm.dx.resource.samplegrad.clamp.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2f32.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE3]], target("dx.Sampler", 0) %[[SAMPLER_H3]], <3 x float> %[[COORD_VAL]], <2 x float> %[[DDX_VAL]], <2 x float> %[[DDY_VAL]], <2 x i32> %[[OFFSET_VAL]], float %[[CLAMP_CAST3]])
+// SPIRV: call {{.*}} <4 x float> @llvm.spv.resource.samplegrad.clamp.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE3]], target("spirv.Sampler") %[[SAMPLER_H3]], <3 x float> %[[COORD_VAL]], <2 x float> %[[DDX_VAL]], <2 x float> %[[DDY_VAL]], <2 x i32> %[[OFFSET_VAL]], float %[[CLAMP_CAST3]])
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleLevel.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleLevel.hlsl
new file mode 100644
index 0000000000000..d6aba2ac0f39b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-SampleLevel.hlsl
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+// DXIL: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) }
+
+// SPIRV: %"class.hlsl::Texture2DArray" = type { target("spirv.Image", float, 1, 2, 1, 0, 1, 0), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") }
+
+Texture2DArray<float4> t;
+SamplerState s;
+
+// CHECK-LABEL: @test_level(float vector[3], float)
+// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleLevel(hlsl::SamplerState, float vector[3], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00)
+// CHECK: ret <4 x float> %[[CALL]]
+
+float4 test_level(float3 loc : LOC, float lod : LOD) : SV_Target {
+ return t.SampleLevel(s, loc, 0.0f);
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleLevel(hlsl::SamplerState, float vector[3], float)(
+// CHECK-SAME: ptr {{.*}} %[[THIS1:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER1:[^,]+]], <3 x float> noundef nofpclass(nan inf) %[[COORD1:[^,]+]], float noundef nofpclass(nan inf) %[[LOD1:[^)]+]])
+// CHECK: %[[THIS_ADDR1:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR1:.*]] = alloca <3 x float>
+// CHECK: %[[LOD_ADDR1:.*]] = alloca float
+// CHECK: store ptr %[[THIS1]], ptr %[[THIS_ADDR1]]
+// CHECK: store <3 x float> %[[COORD1]], ptr %[[COORD_ADDR1]]
+// CHECK: store float %[[LOD1]], ptr %[[LOD_ADDR1]]
+// CHECK: %[[THIS_VAL1:.*]] = load ptr, ptr %[[THIS_ADDR1]]
+// CHECK: %[[HANDLE_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL1]], i32 0, i32 0
+// CHECK: %[[HANDLE1:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP1]]
+// CHECK: %[[SAMPLER_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER1]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H1:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP1]]
+// CHECK: %[[COORD_VAL1:.*]] = load <3 x float>, ptr %[[COORD_ADDR1]]
+// CHECK: %[[LOD_VAL1:.*]] = load float, ptr %[[LOD_ADDR1]]
+// CHECK: %[[LOD_CAST1:.*]] = fptrunc {{.*}} double {{.*}} to float
+// DXIL: call {{.*}} <4 x float> @llvm.dx.resource.samplelevel.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <3 x float> %[[COORD_VAL1]], float %[[LOD_CAST1]], <2 x i32> zeroinitializer)
+// SPIRV: call {{.*}} <4 x float> @llvm.spv.resource.samplelevel.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <3 x float> %[[COORD_VAL1]], float %[[LOD_CAST1]], <2 x i32> zeroinitializer)
+
+// CHECK-LABEL: @test_offset(float vector[3], float)
+// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleLevel(hlsl::SamplerState, float vector[3], float, int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <3 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>)
+// CHECK: ret <4 x float> %[[CALL_OFFSET]]
+
+float4 test_offset(float3 loc : LOC, float lod : LOD) : SV_Target {
+ return t.SampleLevel(s, loc, 0.0f, int2(1, 2));
+}
+
+// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::SampleLevel(hlsl::SamplerState, float vector[3], float, int vector[2])(
+// CHECK-SAME: ptr {{.*}} %[[THIS2:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER2:[^,]+]], <3 x float> noundef nofpclass(nan inf) %[[COORD2:[^,]+]], float noundef nofpclass(nan inf) %[[LOD2:[^,]+]], <2 x i32> noundef %[[OFFSET2:[^)]+]])
+// CHECK: %[[THIS_ADDR2:.*]] = alloca ptr
+// CHECK: %[[COORD_ADDR2:.*]] = alloca <3 x float>
+// CHECK: %[[LOD_ADDR2:.*]] = alloca float
+// CHECK: %[[OFFSET_ADDR2:.*]] = alloca <2 x i32>
+// CHECK: store ptr %[[THIS2]], ptr %[[THIS_ADDR2]]
+// CHECK: store <3 x float> %[[COORD2]], ptr %[[COORD_ADDR2]]
+// CHECK: store float %[[LOD2]], ptr %[[LOD_ADDR2]]
+// CHECK: store <2 x i32> %[[OFFSET2]], ptr %[[OFFSET_ADDR2]]
+// CHECK: %[[THIS_VAL2:.*]] = load ptr, ptr %[[THIS_ADDR2]]
+// CHECK: %[[HANDLE_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2DArray", ptr %[[THIS_VAL2]], i32 0, i32 0
+// CHECK: %[[HANDLE2:.*]] = load target{{.*}}, ptr %[[HANDLE_GEP2]]
+// CHECK: %[[SAMPLER_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::SamplerState", ptr %[[SAMPLER2]], i32 0, i32 0
+// CHECK: %[[SAMPLER_H2:.*]] = load target{{.*}}, ptr %[[SAMPLER_GEP2]]
+// CHECK: %[[COORD_VAL2:.*]] = load <3 x float>, ptr %[[COORD_ADDR2]]
+// CHECK: %[[LOD_VAL2:.*]] = load float, ptr %[[LOD_ADDR2]]
+// CHECK: %[[LOD_CAST2:.*]] = fptrunc {{.*}} double {{.*}} to float
+// CHECK: %[[OFFSET_VAL2:.*]] = load <2 x i32>, ptr %[[OFFSET_ADDR2]]
+// DXIL: call {{.*}} <4 x float> @llvm.dx.resource.samplelevel.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <3 x float> %[[COORD_VAL2]], float %[[LOD_CAST2]], <2 x i32> %[[OFFSET_VAL2]])
+// SPIRV: call {{.*}} <4 x float> @llvm.spv.resource.samplelevel.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <3 x float> %[[COORD_VAL2]], float %[[LOD_CAST2]], <2 x i32> %[[OFFSET_VAL2]])
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-Subscript.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-Subscript.hlsl
new file mode 100644
index 0000000000000..613c36a5d9f6c
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-Subscript.hlsl
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -Wno-sign-conversion -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -Wno-sign-conversion -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+Texture2DArray<float4> Tex : register(t0);
+Texture2DArray<float> Tex2 : register(t1);
+Texture2DArray<int3> Tex3 : register(t2);
+
+[numthreads(1,1,1)]
+void main(uint3 DTid : SV_DispatchThreadID) {
+ float4 val = Tex[DTid];
+ float val2 = Tex2[DTid];
+ int3 val3 = Tex3[DTid];
+}
+
+// CHECK: define hidden {{.*}}void @main(unsigned int vector[3])(<3 x i32> noundef %[[DTID:.*]])
+// CHECK: %[[DTID_ADDR:.*]] = alloca <3 x i32>
+// CHECK: %[[VAL:.*]] = alloca <4 x float>
+// CHECK: %[[VAL2:.*]] = alloca float
+// CHECK: %[[VAL3:.*]] = alloca <3 x i32>
+// CHECK: store <3 x i32> %[[DTID]], ptr %[[DTID_ADDR]]
+// CHECK: %[[DTID_VAL:.*]] = load <3 x i32>, ptr %[[DTID_ADDR]]
+// CHECK: %[[CALL1:.*]] = call noundef {{.*}}ptr{{.*}} @hlsl::Texture2DArray<float vector[4]>::operator[](unsigned int vector[3]) const(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) @Tex, <3 x i32> noundef %[[DTID_VAL]])
+// CHECK: %[[LOAD_VAL:.*]] = load <4 x float>, ptr{{.*}} %[[CALL1]]
+// CHECK: store <4 x float> %[[LOAD_VAL]], ptr %[[VAL]]
+// CHECK: %[[DTID_VAL2:.*]] = load <3 x i32>, ptr %[[DTID_ADDR]]
+// CHECK: %[[CALL2:.*]] = call noundef {{.*}}ptr{{.*}} @hlsl::Texture2DArray<float>::operator[](unsigned int vector[3]) const(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) @Tex2, <3 x i32> noundef %[[DTID_VAL2]])
+// CHECK: %[[LOAD_VAL2:.*]] = load float, ptr{{.*}} %[[CALL2]]
+// CHECK: store float %[[LOAD_VAL2]], ptr %[[VAL2]]
+// CHECK: %[[DTID_VAL3:.*]] = load <3 x i32>, ptr %[[DTID_ADDR]]
+// CHECK: %[[CALL3:.*]] = call noundef {{.*}}ptr{{.*}} @hlsl::Texture2DArray<int vector[3]>::operator[](unsigned int vector[3]) const(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) @Tex3, <3 x i32> noundef %[[DTID_VAL3]])
+// CHECK: %[[LOAD_VAL3:.*]] = load <3 x i32>, ptr{{.*}} %[[CALL3]]
+// CHECK: store <3 x i32> %[[LOAD_VAL3]], ptr %[[VAL3]]
+
+// CHECK: define linkonce_odr hidden noundef {{.*}}ptr{{.*}} @hlsl::Texture2DArray<float vector[4]>::operator[](unsigned int vector[3]) const(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %[[THIS:.*]], <3 x i32> noundef %[[INDEX:.*]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[INDEX_ADDR:.*]] = alloca <3 x i32>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x i32> %[[INDEX]], ptr %[[INDEX_ADDR]]
+// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_PTR:.*]] = getelementptr {{.*}} %"class.hlsl::Texture2DArray", ptr %[[THIS1]], i32 0, i32 0
+// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 7), ptr %[[HANDLE_PTR]]
+// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 1, 0, 1, 0), ptr %[[HANDLE_PTR]]
+// CHECK: %[[INDEX_VAL:.*]] = load <3 x i32>, ptr %[[INDEX_ADDR]]
+// DXIL: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.Texture_v4f32_0_0_0_7t.v3i32(target("dx.Texture", <4 x float>, 0, 0, 0, 7) %[[HANDLE]], <3 x i32> %[[INDEX_VAL]])
+// SPIRV: %[[PTR:.*]] = call ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_f32_1_2_1_0_1_0t.v3i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], <3 x i32> %[[INDEX_VAL]])
+// CHECK: ret ptr {{.*}}%[[PTR]]
+
+// CHECK: define linkonce_odr hidden noundef {{.*}}ptr{{.*}} @hlsl::Texture2DArray<float>::operator[](unsigned int vector[3]) const(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %[[THIS:.*]], <3 x i32> noundef %[[INDEX:.*]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[INDEX_ADDR:.*]] = alloca <3 x i32>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x i32> %[[INDEX]], ptr %[[INDEX_ADDR]]
+// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_PTR:.*]] = getelementptr {{.*}} %"class.hlsl::Texture2DArray.0", ptr %[[THIS1]], i32 0, i32 0
+// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", float, 0, 0, 0, 7), ptr %[[HANDLE_PTR]]
+// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 1, 0, 1, 0), ptr %[[HANDLE_PTR]]
+// CHECK: %[[INDEX_VAL:.*]] = load <3 x i32>, ptr %[[INDEX_ADDR]]
+// DXIL: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.Texture_f32_0_0_0_7t.v3i32(target("dx.Texture", float, 0, 0, 0, 7) %[[HANDLE]], <3 x i32> %[[INDEX_VAL]])
+// SPIRV: %[[PTR:.*]] = call ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_f32_1_2_1_0_1_0t.v3i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %[[HANDLE]], <3 x i32> %[[INDEX_VAL]])
+// CHECK: ret ptr {{.*}}%[[PTR]]
+
+// CHECK: define linkonce_odr hidden noundef {{.*}}ptr{{.*}} @hlsl::Texture2DArray<int vector[3]>::operator[](unsigned int vector[3]) const(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %[[THIS:.*]], <3 x i32> noundef %[[INDEX:.*]])
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+// CHECK: %[[INDEX_ADDR:.*]] = alloca <3 x i32>
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]]
+// CHECK: store <3 x i32> %[[INDEX]], ptr %[[INDEX_ADDR]]
+// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[HANDLE_PTR:.*]] = getelementptr {{.*}} %"class.hlsl::Texture2DArray{{.*}}", ptr %[[THIS1]], i32 0, i32 0
+// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <3 x i32>, 0, 0, 1, 7), ptr %[[HANDLE_PTR]]
+// SPIRV: %[[HANDLE:.*]] = load target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0), ptr %[[HANDLE_PTR]]
+// CHECK: %[[INDEX_VAL:.*]] = load <3 x i32>, ptr %[[INDEX_ADDR]]
+// DXIL: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.Texture_v3i32_0_0_1_7t.v3i32(target("dx.Texture", <3 x i32>, 0, 0, 1, 7) %[[HANDLE]], <3 x i32> %[[INDEX_VAL]])
+// SPIRV: %[[PTR:.*]] = call ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_1_2_1_0_1_0t.v3i32(target("spirv.SignedImage", i32, 1, 2, 1, 0, 1, 0) %[[HANDLE]], <3 x i32> %[[INDEX_VAL]])
+// CHECK: ret ptr {{.*}}%[[PTR]]
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-default-explicit-binding.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-default-explicit-binding.hlsl
new file mode 100644
index 0000000000000..71e2881420592
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-default-explicit-binding.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=SPIRV
+
+SamplerState g_s : register(s0);
+Texture2DArray<> default_template : register(t1, space2);
+Texture2DArray implicit_template : register(t0, space1);
+
+// CHECK: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// SPIRV: %"class.hlsl::Texture2DArray" = type { target("spirv.Image", float, 1, 2, 1, 0, 1, 0), %"struct.hlsl::Texture2DArray<>::mips_type" }
+
+// CHECK: @{{.*}}default_template = internal global %"class.hlsl::Texture2DArray" poison, align {{[0-9]+}}
+// CHECK: @{{.*}}implicit_template = internal global %"class.hlsl::Texture2DArray" poison, align {{[0-9]+}}
+// SPIRV: @{{.*}}default_template = internal global %"class.hlsl::Texture2DArray" poison, align {{[0-9]+}}
+// SPIRV: @{{.*}}implicit_template = internal global %"class.hlsl::Texture2DArray" poison, align {{[0-9]+}}
+
+[shader("pixel")]
+float4 main(float3 uv : TEXCOORD) : SV_Target {
+ return implicit_template.Sample(g_s, uv) + default_template.Sample(g_s, uv);
+}
+
+// CHECK: call void @{{.*}}__createFromBinding{{.*}}(ptr {{.*}}@{{.*}}default_template, i32 noundef 1, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @{{.*}})
+// CHECK: call void @{{.*}}__createFromBinding{{.*}}(ptr {{.*}}@{{.*}}implicit_template, i32 noundef 0, i32 noundef 1, i32 noundef 1, i32 noundef 0, ptr noundef @{{.*}})
+// SPIRV: call void @{{.*}}__createFromBinding{{.*}}(ptr {{.*}}@{{.*}}default_template, i32 noundef 1, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @{{.*}})
+// SPIRV: call void @{{.*}}__createFromBinding{{.*}}(ptr {{.*}}@{{.*}}implicit_template, i32 noundef 0, i32 noundef 1, i32 noundef 1, i32 noundef 0, ptr noundef @{{.*}})
+// CHECK: define void @main()
+// SPIRV: define void @main()
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-default.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-default.hlsl
new file mode 100644
index 0000000000000..ccbd580cba3d4
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-default.hlsl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -std=hlsl202x -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+// CHECK: %"class.hlsl::Texture2DArray.0" = type { target("dx.Texture", float, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<float>::mips_type" }
+
+// CHECK: @{{.*}}t1 = internal global %"class.hlsl::Texture2DArray" poison, align 4
+Texture2DArray<> t1;
+
+// CHECK: @{{.*}}t2 = internal global %"class.hlsl::Texture2DArray.0" poison, align 4
+Texture2DArray<float> t2;
+
+// CHECK: @{{.*}}t3 = internal global %"class.hlsl::Texture2DArray" poison, align 4
+Texture2DArray t3;
+
+void main() {
+}
diff --git a/clang/test/CodeGenHLSL/resources/Texture2DArray-shorthand-contexts.hlsl b/clang/test/CodeGenHLSL/resources/Texture2DArray-shorthand-contexts.hlsl
new file mode 100644
index 0000000000000..78ba7f699000f
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Texture2DArray-shorthand-contexts.hlsl
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s
+
+// CHECK: %"class.hlsl::Texture2DArray" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 7), %"struct.hlsl::Texture2DArray<>::mips_type" }
+
+SamplerState g_s : register(s0);
+
+struct S {
+ Texture2DArray tex;
+};
+
+// CHECK: define {{.*}}void @use_struct(S)(ptr noundef {{.*}}%s)
+void use_struct(S s) {
+ // CHECK: call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3])
+ float4 val = s.tex.Sample(g_s, float3(0.5, 0.5, 0.1));
+}
+
+// CHECK: define {{.*}}void @use_param(hlsl::Texture2DArray<float vector[4]>)(ptr noundef {{.*}}%p)
+void use_param(Texture2DArray p) {
+ // CHECK: call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3])
+ float4 val = p.Sample(g_s, float3(0.5, 0.5, 0.1));
+}
+
+[shader("pixel")]
+float4 main() : SV_Target {
+ // CHECK: %local = alloca %"class.hlsl::Texture2DArray"
+ Texture2DArray local;
+ // CHECK: call {{.*}} <4 x float> @hlsl::Texture2DArray<float vector[4]>::Sample(hlsl::SamplerState, float vector[3])
+ return local.Sample(g_s, float3(0.5, 0.5, 0.1));
+}
+
+// CHECK: declare <4 x float> @llvm.dx.resource.sample.v4f32
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-CalculateLevelOfDetail.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-CalculateLevelOfDetail.hlsl
new file mode 100644
index 0000000000000..9d26af51a120b
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-CalculateLevelOfDetail.hlsl
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s
+
+Texture2DArray<float4> tex;
+SamplerState samp;
+
+void main() {
+ float2 loc = float2(0, 0);
+
+ tex.CalculateLevelOfDetail(samp, loc);
+ tex.CalculateLevelOfDetailUnclamped(samp, loc);
+
+ // expected-error at +2 {{too few arguments to function call, expected 2, have 1}}
+ // expected-note@* {{'CalculateLevelOfDetail' declared here}}
+ tex.CalculateLevelOfDetail(samp);
+
+ // expected-error at +2 {{too few arguments to function call, expected 2, have 1}}
+ // expected-note@* {{'CalculateLevelOfDetailUnclamped' declared here}}
+ tex.CalculateLevelOfDetailUnclamped(samp);
+
+ // expected-error at +2 {{too many arguments to function call, expected 2, have 3}}
+ // expected-note@* {{'CalculateLevelOfDetail' declared here}}
+ tex.CalculateLevelOfDetail(samp, loc, 0);
+
+ // expected-error at +2{{too many arguments to function call, expected 2, have 3}}
+ // expected-note@* {{'CalculateLevelOfDetailUnclamped' declared here}}
+ tex.CalculateLevelOfDetailUnclamped(samp, loc, 0);
+
+ // expected-error at +1 {{cannot initialize a parameter of type 'vector<float, 2>' (vector of 2 'float' values) with an lvalue of type 'const char[8]'}}
+ tex.CalculateLevelOfDetail(samp, "invalid");
+
+ // expected-error at +1 {{cannot initialize a parameter of type 'vector<float, 2>' (vector of 2 'float' values) with an lvalue of type 'const char[8]'}}
+ tex.CalculateLevelOfDetailUnclamped(samp, "invalid");
+}
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-GetDimensions.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-GetDimensions.hlsl
new file mode 100644
index 0000000000000..21f69d4fe837f
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-GetDimensions.hlsl
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s
+
+Texture2DArray<float4> tex;
+
+void main() {
+ uint u_w, u_h, u_l;
+ float f_w, f_h, f_l;
+
+ // Valid calls
+ tex.GetDimensions(u_w, u_h);
+ tex.GetDimensions(0, u_w, u_h, u_l);
+ tex.GetDimensions(f_w, f_h);
+ tex.GetDimensions(0, f_w, f_h, f_l);
+
+ // Invalid number of arguments
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions();
+ // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 0 were provided}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 0 were provided}}
+
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(u_w);
+ // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 1 was provided}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 1 was provided}}
+
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(u_w, u_h, u_l);
+ // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 3 were provided}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 3 were provided}}
+
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(0, u_w, u_h, u_l, 0);
+ // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 5 were provided}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 5 were provided}}
+
+ // Invalid types
+ int i_w, i_h;
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(i_w, i_h);
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'int' to 'unsigned int &__restrict' for 1st argument}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'int' to 'float &__restrict' for 1st argument}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 2 were provided}}
+
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(u_w, i_h);
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'int' to 'unsigned int &__restrict' for 2nd argument}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'uint' (aka 'unsigned int') to 'float &__restrict' for 1st argument}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 2 were provided}}
+
+ // Invalid lvalues
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(0u, u_h);
+ // expected-note@*:* {{candidate function not viable: expects an lvalue for 1st argument}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'unsigned int' to 'float &__restrict' for 1st argument}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 2 were provided}}
+
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(u_w, 0u);
+ // expected-note@*:* {{candidate function not viable: expects an lvalue for 2nd argument}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'uint' (aka 'unsigned int') to 'float &__restrict' for 1st argument}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 2 were provided}}
+
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(0, 0u, u_h, u_l);
+ // expected-note@*:* {{candidate function not viable: expects an lvalue for 2nd argument}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'unsigned int' to 'float &__restrict' for 2nd argument}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 4 were provided}}
+
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(0, u_w, 0u, u_l);
+ // expected-note@*:* {{candidate function not viable: expects an lvalue for 3rd argument}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'uint' (aka 'unsigned int') to 'float &__restrict' for 2nd argument}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 4 were provided}}
+
+ // expected-error at +1 {{no matching member function for call to 'GetDimensions'}}
+ tex.GetDimensions(0, u_w, u_h, 0u);
+ // expected-note@*:* {{candidate function not viable: expects an lvalue for 4th argument}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'uint' (aka 'unsigned int') to 'float &__restrict' for 2nd argument}}
+ // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 4 were provided}}
+}
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-SampleBias.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleBias.hlsl
new file mode 100644
index 0000000000000..53d2d417f8dfb
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleBias.hlsl
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s
+
+Texture2DArray<float4> tex;
+SamplerState samp;
+
+void main() {
+ float3 loc = float3(0, 0, 0);
+ float bias = 0;
+ int2 offset = int2(0, 0);
+ float clamp = 0;
+
+ tex.SampleBias(samp, loc, bias);
+ tex.SampleBias(samp, loc, bias, offset);
+ tex.SampleBias(samp, loc, bias, offset, clamp);
+
+ // Too few arguments.
+ tex.SampleBias(samp, loc); // expected-error {{no matching member function for call to 'SampleBias'}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 2 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 2 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 2 were provided}}
+
+ // Too many arguments.
+ tex.SampleBias(samp, loc, bias, offset, clamp, 0); // expected-error {{no matching member function for call to 'SampleBias'}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 6 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 6 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 6 were provided}}
+
+ // Invalid argument types.
+ tex.SampleBias(samp, loc, bias, offset, "invalid"); // expected-error {{no matching member function for call to 'SampleBias'}}
+ // expected-note@*:* {{no known conversion from 'const char[8]' to 'float' for 5th argument}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 5 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 5 were provided}}
+}
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-SampleCmp.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleCmp.hlsl
new file mode 100644
index 0000000000000..50e6ff5142e04
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleCmp.hlsl
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -fsyntax-only -finclude-default-header -verify %s
+
+
+Texture2DArray<float4> t;
+Texture2DArray<int4> t_int;
+SamplerComparisonState s;
+SamplerState s2;
+
+void main(float3 loc, float cmp) {
+ t.SampleCmp(s, loc, cmp);
+ t.SampleCmp(s, loc, cmp, int2(1, 2));
+ t.SampleCmp(s, loc, cmp, int2(1, 2), 1.0f);
+
+ // expected-error@* {{'SampleCmp' and 'SampleCmpLevelZero' require resource to contain a floating point type}}
+ // expected-note@*:* {{in instantiation of member function 'hlsl::Texture2DArray<vector<int, 4>>::SampleCmp' requested here}}
+ t_int.SampleCmp(s, loc, cmp);
+
+ // expected-error at +4 {{no matching member function for call to 'SampleCmp'}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 1 was provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 1 was provided}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 1 was provided}}
+ t.SampleCmp(loc);
+
+ // expected-error at +4 {{no matching member function for call to 'SampleCmp'}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 6 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 6 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 6 were provided}}
+ t.SampleCmp(s, loc, cmp, int2(1, 2), 1.0f, 1.0f);
+
+ // expected-error at +4 {{no matching member function for call to 'SampleCmp'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'SamplerState' to 'hlsl::SamplerComparisonState' for 1st argument}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 3 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 3 were provided}}
+ t.SampleCmp(s2, loc, cmp);
+
+ // expected-error at +4 {{no matching member function for call to 'SampleCmp'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'SamplerComparisonState' to 'vector<int, 2>' (vector of 2 'int' values) for 4th argument}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 4 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 4 were provided}}
+ t.SampleCmp(s, loc, cmp, s);
+
+ // expected-error at +4 {{no matching member function for call to 'SampleCmp'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'SamplerComparisonState' to 'float' for 5th argument}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 5 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 5 were provided}}
+ t.SampleCmp(s, loc, cmp, int2(1, 2), s);
+}
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-SampleCmpLevelZero.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleCmpLevelZero.hlsl
new file mode 100644
index 0000000000000..6908b9fb85b1f
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleCmpLevelZero.hlsl
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -fsyntax-only -finclude-default-header -verify %s
+
+// expected-error@* {{'SampleCmp' and 'SampleCmpLevelZero' require resource to contain a floating point type}}
+
+Texture2DArray<float4> t;
+Texture2DArray<int4> t_int;
+SamplerComparisonState s;
+SamplerState s2;
+
+void main(float3 loc, float cmp) {
+ t.SampleCmpLevelZero(s, loc, cmp);
+ t.SampleCmpLevelZero(s, loc, cmp, int2(1, 2));
+
+ // expected-note@*:* {{in instantiation of member function 'hlsl::Texture2DArray<vector<int, 4>>::SampleCmpLevelZero' requested here}}
+ t_int.SampleCmpLevelZero(s, loc, cmp);
+
+ // expected-error at +3 {{no matching member function for call to 'SampleCmpLevelZero'}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 1 was provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 1 was provided}}
+ t.SampleCmpLevelZero(loc);
+
+ // expected-error at +3 {{no matching member function for call to 'SampleCmpLevelZero'}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 5 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 5 were provided}}
+ t.SampleCmpLevelZero(s, loc, cmp, int2(1, 2), 1.0f);
+
+ // expected-error at +3 {{no matching member function for call to 'SampleCmpLevelZero'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'SamplerState' to 'hlsl::SamplerComparisonState' for 1st argument}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 3 were provided}}
+ t.SampleCmpLevelZero(s2, loc, cmp);
+
+ // expected-error at +3 {{no matching member function for call to 'SampleCmpLevelZero'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'SamplerComparisonState' to 'vector<int, 2>' (vector of 2 'int' values) for 4th argument}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 4 were provided}}
+ t.SampleCmpLevelZero(s, loc, cmp, s);
+}
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-SampleGrad.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleGrad.hlsl
new file mode 100644
index 0000000000000..36f6564473a2c
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleGrad.hlsl
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s
+
+Texture2DArray<float4> tex;
+SamplerState samp;
+
+void main() {
+ float3 loc = float3(0, 0, 0);
+ float2 ddx = float2(0, 0);
+ float2 ddy = float2(0, 0);
+ int2 offset = int2(0, 0);
+ float clamp = 0;
+
+ tex.SampleGrad(samp, loc, ddx, ddy);
+ tex.SampleGrad(samp, loc, ddx, ddy, offset);
+ tex.SampleGrad(samp, loc, ddx, ddy, offset, clamp);
+
+ // Too few arguments.
+ tex.SampleGrad(samp, loc, ddx); // expected-error {{no matching member function for call to 'SampleGrad'}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 3 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 3 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 6 arguments, but 3 were provided}}
+
+ // Too many arguments.
+ tex.SampleGrad(samp, loc, ddx, ddy, offset, clamp, 0); // expected-error {{no matching member function for call to 'SampleGrad'}}
+ // expected-note@*:* {{candidate function not viable: requires 6 arguments, but 7 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 7 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 7 were provided}}
+
+ // Invalid argument types.
+ tex.SampleGrad(samp, loc, ddx, ddy, offset, "invalid"); // expected-error {{no matching member function for call to 'SampleGrad'}}
+ // expected-note@*:* {{no known conversion from 'const char[8]' to 'float' for 6th argument}}
+ // expected-note@*:* {{candidate function not viable: requires 5 arguments, but 6 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 6 were provided}}
+}
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-SampleLevel.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleLevel.hlsl
new file mode 100644
index 0000000000000..c62eccdb7688e
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-SampleLevel.hlsl
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s
+
+Texture2DArray<float4> tex;
+SamplerState samp;
+
+void main() {
+ float3 loc = float3(0, 0, 0);
+ float lod = 0;
+ int2 offset = int2(0, 0);
+
+ tex.SampleLevel(samp, loc, lod);
+ tex.SampleLevel(samp, loc, lod, offset);
+
+ // Too few arguments.
+ tex.SampleLevel(samp, loc); // expected-error {{no matching member function for call to 'SampleLevel'}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 2 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 2 were provided}}
+
+ // Too many arguments.
+ tex.SampleLevel(samp, loc, lod, offset, 0); // expected-error {{no matching member function for call to 'SampleLevel'}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 5 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 5 were provided}}
+
+ // Invalid argument types.
+ tex.SampleLevel(samp, loc, "invalid"); // expected-error {{no matching member function for call to 'SampleLevel'}}
+ // expected-note@*:* {{no known conversion from 'const char[8]' to 'float' for 3rd argument}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 3 were provided}}
+}
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-Sema.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-Sema.hlsl
new file mode 100644
index 0000000000000..8d0dda855eab4
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-Sema.hlsl
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -fsyntax-only -finclude-default-header -verify %s
+
+Texture2DArray<float4> t;
+SamplerState s;
+
+void main(float3 loc) {
+ t.Sample(s, loc);
+ t.Sample(s, loc, int2(1, 2));
+
+ // expected-error at +4 {{no matching member function for call to 'Sample'}}
+ // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 1 was provided}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 1 was provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 1 was provided}}
+ t.Sample(loc);
+
+ t.Sample(s, loc, int2(1, 2), 1.0);
+
+ // expected-error at +4 {{no matching member function for call to 'Sample'}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 5 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 5 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 5 were provided}}
+ t.Sample(s, loc, int2(1, 2), 1.0, 1.0);
+
+ // expected-error at +4 {{no matching member function for call to 'Sample'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'SamplerState' to 'vector<int, 2>' (vector of 2 'int' values) for 3rd argument}}
+ // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 4 arguments, but 3 were provided}}
+ t.Sample(s, loc, s);
+
+ // expected-error at +4 {{no matching member function for call to 'Sample'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'SamplerState' to 'float' for 4th argument}}
+ // expected-note@*:* {{candidate function not viable: requires 3 arguments, but 4 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 4 were provided}}
+ t.Sample(s, loc, int2(1, 2), s);
+
+ // Test with wrong coordinate dimension.
+ // Note: float implicitly converts to float3 (splat), so no error here.
+ t.Sample(s, loc.x);
+
+ // Test with wrong offset dimension.
+ // Note: int implicitly converts to int2 (splat), so no error here.
+ t.Sample(s, loc, 1);
+}
diff --git a/clang/test/SemaHLSL/Resources/Texture2DArray-Subscript.hlsl b/clang/test/SemaHLSL/Resources/Texture2DArray-Subscript.hlsl
new file mode 100644
index 0000000000000..addb46275dc31
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Texture2DArray-Subscript.hlsl
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -finclude-default-header -verify -o - %s
+
+Texture2DArray<float4> Tex;
+
+struct S { int a; };
+
+void main() {
+ uint3 valid_index = uint3(1, 2, 0);
+ float4 val1 = Tex[valid_index]; // OK
+
+ S s = { 1 };
+ // expected-error at +2 {{no viable overloaded operator[] for type 'Texture2DArray<float4>'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'S' to 'vector<unsigned int, 3>'}}
+ float4 val2 = Tex[s];
+
+ int i = 1;
+ float4 val3 = Tex[i]; // expected-warning {{implicit conversion changes signedness: 'int' to 'vector<unsigned int, 3>' (vector of 3 'unsigned int' values)}}
+
+ int4 i4 = int4(1, 2, 3, 4);
+ // expected-warning at +2 {{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'vector<unsigned int, 3>' (vector of 3 'unsigned int' values)}}
+ // expected-warning at +1 {{implicit conversion changes signedness: 'int4' (aka 'vector<int, 4>') to 'vector<unsigned int, 3>' (vector of 3 'unsigned int' values)}}
+ float4 val4 = Tex[i4];
+
+ uint2 too_few = uint2(1, 2);
+ // expected-error at +2 {{no viable overloaded operator[] for type 'Texture2DArray<float4>'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'uint2' (aka 'vector<uint, 2>') to 'vector<unsigned int, 3>'}}
+ float4 val5 = Tex[too_few];
+}
diff --git a/clang/test/SemaHLSL/Texture2DArray-Gather.hlsl b/clang/test/SemaHLSL/Texture2DArray-Gather.hlsl
new file mode 100644
index 0000000000000..9adcb4d8f22e7
--- /dev/null
+++ b/clang/test/SemaHLSL/Texture2DArray-Gather.hlsl
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -fsyntax-only -verify -finclude-default-header %s
+
+Texture2DArray<float4> Tex;
+SamplerState Samp;
+SamplerComparisonState SampCmp;
+
+void main() {
+ float3 uv = float3(0.5, 0.5, 0.0);
+ int2 offset = int2(1, 1);
+ float compare = 0.5;
+
+ // Gather
+ // Expected: Gather(SamplerState, float3, [int2])
+ Tex.Gather(Samp, uv);
+ Tex.Gather(Samp, uv, offset);
+
+ // Invalid Overloads
+ Tex.Gather(Samp); // expected-error {{no matching member function for call to 'Gather'}}
+ Tex.Gather(Samp, uv, offset, 1); // expected-error {{no matching member function for call to 'Gather'}}
+
+ // Gather variants
+ Tex.GatherRed(Samp, uv);
+ Tex.GatherGreen(Samp, uv, offset);
+ Tex.GatherBlue(Samp, uv);
+ Tex.GatherAlpha(Samp, uv, offset);
+
+ // GatherCmp
+ // Expected: GatherCmp(SamplerComparisonState, float3, float, [int2])
+ Tex.GatherCmp(SampCmp, uv, compare);
+ Tex.GatherCmp(SampCmp, uv, compare, offset);
+
+ // Invalid Overloads
+ Tex.GatherCmp(SampCmp, uv); // expected-error {{no matching member function for call to 'GatherCmp'}}
+ Tex.GatherCmp(SampCmp, uv, compare, offset, 1); // expected-error {{no matching member function for call to 'GatherCmp'}}
+
+ // GatherCmp variants
+ Tex.GatherCmpRed(SampCmp, uv, compare);
+ Tex.GatherCmpGreen(SampCmp, uv, compare);
+ Tex.GatherCmpBlue(SampCmp, uv, compare, offset);
+ Tex.GatherCmpAlpha(SampCmp, uv, compare);
+
+ // Type checks
+ // Offset must be int2 (SamplerState fails)
+ Tex.Gather(Samp, uv, Samp); // expected-error {{no matching member function for call to 'Gather'}}
+
+ // Compare value must be scalar float
+ Tex.GatherCmp(SampCmp, uv, Samp); // expected-error {{no matching member function for call to 'GatherCmp'}}
+}
+
+// expected-note@* 0+{{candidate function not viable}}
diff --git a/clang/test/SemaHLSL/Texture2DArray-GatherCmp-Vulkan.hlsl b/clang/test/SemaHLSL/Texture2DArray-GatherCmp-Vulkan.hlsl
new file mode 100644
index 0000000000000..e8a9a64ef473e
--- /dev/null
+++ b/clang/test/SemaHLSL/Texture2DArray-GatherCmp-Vulkan.hlsl
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -fsyntax-only -verify -finclude-default-header %s
+
+Texture2DArray<float4> Tex;
+SamplerComparisonState SampCmp;
+
+void main() {
+ float3 uv = float3(0.5, 0.5, 0.0);
+ float compare = 0.5;
+
+ Tex.GatherCmp(SampCmp, uv, compare);
+ Tex.GatherCmpRed(SampCmp, uv, compare);
+
+ // expected-error@* {{gatherCmpGreen operations on the Vulkan target are not supported; only GatherCmp and GatherCmpRed are allowed}}
+ Tex.GatherCmpGreen(SampCmp, uv, compare);
+
+ // expected-error@* {{gatherCmpBlue operations on the Vulkan target are not supported; only GatherCmp and GatherCmpRed are allowed}}
+ Tex.GatherCmpBlue(SampCmp, uv, compare);
+
+ // expected-error@* {{gatherCmpAlpha operations on the Vulkan target are not supported; only GatherCmp and GatherCmpRed are allowed}}
+ Tex.GatherCmpAlpha(SampCmp, uv, compare);
+}
+
+// expected-note@* 0+{{in instantiation of member function}}
diff --git a/clang/test/SemaHLSL/Texture2DArray-Load-errors.hlsl b/clang/test/SemaHLSL/Texture2DArray-Load-errors.hlsl
new file mode 100644
index 0000000000000..36427aab0e604
--- /dev/null
+++ b/clang/test/SemaHLSL/Texture2DArray-Load-errors.hlsl
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -finclude-default-header -verify %s
+
+Texture2DArray<float4> t;
+
+float4 test_too_few_args() {
+ return t.Load(); // expected-error {{no matching member function for call to 'Load'}}
+ // expected-note@*:* {{candidate function not viable: requires single argument 'Location', but no arguments were provided}}
+ // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 0 were provided}}
+}
+
+float4 test_too_many_args(int3 loc) {
+ return t.Load(int4(loc, 0), int2(1, 1), 1); // expected-error {{no matching member function for call to 'Load'}}
+ // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
+ // expected-note@*:* {{candidate function not viable: requires single argument 'Location', but 3 arguments were provided}}
+}
+
+float4 test_invalid_coord_type(float3 loc) {
+ return t.Load(float4(loc, 0)); // expected-warning {{implicit conversion turns floating-point number into integer: 'float4' (aka 'vector<float, 4>') to 'vector<int, 4>'}}
+}
+
+float4 test_invalid_offset_type(int3 loc, float2 offset) {
+ return t.Load(int4(loc, 0), offset); // expected-warning {{implicit conversion turns floating-point number into integer: 'float2' (aka 'vector<float, 2>') to 'vector<int, 2>'}}
+}
+
+float4 test_invalid_location_count(int2 loc) {
+ return t.Load(loc); // expected-error {{no matching member function for call to 'Load'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'int2' (aka 'vector<int, 2>') to 'vector<int, 4>' (vector of 4 'int' values) for 1st argument}}
+ // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 1 was provided}}
+}
+
+float4 test_short_location_count(int3 loc) {
+ return t.Load(loc); // expected-error {{no matching member function for call to 'Load'}}
+ // expected-note@*:* {{candidate function not viable: no known conversion from 'int3' (aka 'vector<int, 3>') to 'vector<int, 4>' (vector of 4 'int' values) for 1st argument}}
+ // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 1 was provided}}
+}
+
+float4 test_splatted_offset_count(int4 loc, int offset) {
+ // No errors expected. The vector will be generated by splatting `offset`.
+ return t.Load(loc, offset);
+}
+
+float4 test_truncated_offset_count(int3 loc, int3 offset) {
+ return t.Load(int4(loc, 0), offset); // expected-warning {{implicit conversion truncates vector: 'int3' (aka 'vector<int, 3>') to 'vector<int, 2>' (vector of 2 'int' values)}}
+}
diff --git a/clang/test/SemaHLSL/Texture2DArray-mips-errors.hlsl b/clang/test/SemaHLSL/Texture2DArray-mips-errors.hlsl
new file mode 100644
index 0000000000000..c9a988a1a0537
--- /dev/null
+++ b/clang/test/SemaHLSL/Texture2DArray-mips-errors.hlsl
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm-only -disable-llvm-passes -finclude-default-header -verify %s
+
+Texture2DArray<float4> t;
+
+template<class T>
+float4 foo(T t) {
+ int3 c = {0, 0, 0};
+ return t[c];
+}
+
+[shader("pixel")]
+float4 test_mips() : SV_Target {
+ // expected-error at +4 {{'mips_type' is a private member of 'hlsl::Texture2DArray<>'}}
+ // expected-note@*:* {{implicitly declared private here}}
+ // expected-error at +2 {{calling a protected constructor of class 'hlsl::Texture2DArray<>::mips_type'}}
+ // expected-note@*:* {{implicitly declared protected here}}
+ Texture2DArray<float4>::mips_type a;
+
+ // expected-error at +4 {{'mips_slice_type' is a private member of 'hlsl::Texture2DArray<>'}}
+ // expected-note@*:* {{implicitly declared private here}}
+ // expected-error at +2 {{calling a protected constructor of class 'hlsl::Texture2DArray<>::mips_slice_type'}}
+ // expected-note@*:* {{implicitly declared protected here}}
+ Texture2DArray<float4>::mips_slice_type b;
+
+ // expected-warning at +3 {{'auto' type specifier is a HLSL 202y extension}}
+ // expected-error at +2 {{calling a protected constructor of class 'hlsl::Texture2DArray<>::mips_type'}}
+ // expected-note@*:* {{implicitly declared protected here}}
+ auto c = t.mips;
+
+ // expected-error at +2 {{calling a protected constructor of class 'hlsl::Texture2DArray<>::mips_slice_type'}}
+ // expected-note@*:* {{implicitly declared protected here}}
+ return t.mips[0][int3(0, 0, 0)] + foo(t.mips[0]);
+}
diff --git a/llvm/test/CodeGen/DirectX/Texture2DArray-SampleBias.ll b/llvm/test/CodeGen/DirectX/Texture2DArray-SampleBias.ll
new file mode 100644
index 0000000000000..84a77920bcbed
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Texture2DArray-SampleBias.ll
@@ -0,0 +1,96 @@
+; RUN: opt -S -dxil-op-lower %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.6-pixel"
+
+declare void @use_float4(<4 x float>)
+
+; Test SampleBias on a Texture2DArray with float4 result.
+; CHECK-LABEL: define void @samplebias_texture2darray_float4(
+define void @samplebias_texture2darray_float4(<3 x float> %coords, float %bias) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %[[COORD0]], float %[[COORD1]], float %[[COORD2]], float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float %bias,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplebias.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <3 x float> %coords, float %bias, <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
+
+; Test SampleBias with constant non-zero offsets on a Texture2DArray.
+; CHECK-LABEL: define void @samplebias_texture2darray_with_offset(
+define void @samplebias_texture2darray_with_offset(<3 x float> %coords, float %bias) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %[[COORD0]], float %[[COORD1]], float %[[COORD2]], float undef,
+ ; CHECK-SAME: i32 1, i32 -2, i32 undef,
+ ; CHECK-SAME: float %bias,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplebias.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <3 x float> %coords, float %bias, <2 x i32> <i32 1, i32 -2>)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
+
+; Test SampleBias with clamp on a Texture2DArray.
+; CHECK-LABEL: define void @samplebias_texture2darray_with_clamp(
+define void @samplebias_texture2darray_with_clamp(<3 x float> %coords, float %bias, float %clamp) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
+ ; CHECK-SAME: float %{{[^,]*}}, float %{{[^,]*}}, float %{{[^,]*}}, float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float %bias,
+ ; CHECK-SAME: float %clamp)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplebias.clamp.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <3 x float> %coords, float %bias, <2 x i32> zeroinitializer, float %clamp)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/Texture2DArray-SampleGrad.ll b/llvm/test/CodeGen/DirectX/Texture2DArray-SampleGrad.ll
new file mode 100644
index 0000000000000..214906036542a
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Texture2DArray-SampleGrad.ll
@@ -0,0 +1,72 @@
+; RUN: opt -S -dxil-op-lower %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.6-pixel"
+
+declare void @use_float4(<4 x float>)
+
+; Test basic SampleGrad on a Texture2DArray with float4 result.
+; CHECK-LABEL: define void @samplegrad_texture2darray_float4(
+define void @samplegrad_texture2darray_float4(<3 x float> %coords, <2 x float> %ddx, <2 x float> %ddy) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %[[COORD0]], float %[[COORD1]], float %[[COORD2]], float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float %[[DDX0]], float %[[DDX1]], float undef,
+ ; CHECK-SAME: float %[[DDY0]], float %[[DDY1]], float undef,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplegrad.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2f32.v2f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <3 x float> %coords, <2 x float> %ddx, <2 x float> %ddy,
+ <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
+
+; Test SampleGrad with constant non-zero offsets on a Texture2DArray.
+; CHECK-LABEL: define void @samplegrad_texture2darray_with_offset(
+define void @samplegrad_texture2darray_with_offset(<3 x float> %coords, <2 x float> %ddx, <2 x float> %ddy) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
+ ; CHECK-SAME: float %{{[^,]*}}, float %{{[^,]*}}, float %{{[^,]*}}, float undef,
+ ; CHECK-SAME: i32 1, i32 -2, i32 undef,
+ ; CHECK-SAME: float %{{[^,]*}}, float %{{[^,]*}}, float undef,
+ ; CHECK-SAME: float %{{[^,]*}}, float %{{[^,]*}}, float undef,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplegrad.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2f32.v2f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <3 x float> %coords, <2 x float> %ddx, <2 x float> %ddy,
+ <2 x i32> <i32 1, i32 -2>)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/Texture2DArray-annotateHandle.ll b/llvm/test/CodeGen/DirectX/Texture2DArray-annotateHandle.ll
new file mode 100644
index 0000000000000..c5973f609ee90
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Texture2DArray-annotateHandle.ll
@@ -0,0 +1,33 @@
+; RUN: opt -S -passes=dxil-translate-metadata,dxil-op-lower %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.6-pixel"
+
+declare void @use_float4(<4 x float>)
+
+; CHECK: @[[TEX2DARR:[0-9]+]] = external constant %"Texture2DArray<float4>"
+
+; Test that a Texture2DArray handle gets ResourceKind::Texture2DArray metadata.
+; CHECK-LABEL: define void @annotate_texture2darray_float4(
+define void @annotate_texture2darray_float4(<3 x float> %coords, float %bias) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
+ i32 0, i32 5, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ ; CHECK: %[[TEX:.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 5, i32 5, i32 0, i8 0 }, i32 5, i1 false)
+ ; CHECK: %[[TEX_ANNOT:.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %[[TEX]], %dx.types.ResourceProperties { i32 7, i32 1033 })
+ ; CHECK: call %dx.types.ResRet.f32 @dx.op.sampleBias.f32(i32 61, %dx.types.Handle %[[TEX_ANNOT]]
+ %data = call <4 x float>
+ @llvm.dx.resource.samplebias.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <3 x float> %coords, float %bias, <2 x i32> zeroinitializer)
+
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
+; Test that the metadata ResourceKind is Texture2DArray (=7), and element type is F32
+; CHECK: !{{[0-9]+}} = !{i32 0, ptr @[[TEX2DARR]], !"", i32 0, i32 5, i32 1, i32 7, i32 0, ![[TAG:[0-9]+]]}
+; CHECK: ![[TAG]] = !{i32 0, i32 9}
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/Gather2DArray.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/Gather2DArray.ll
new file mode 100644
index 0000000000000..b26e27d40015f
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/Gather2DArray.ll
@@ -0,0 +1,44 @@
+; RUN: llc -O0 -mtriple=spirv-vulkan1.3-compute %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan1.3-compute %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: OpCapability Shader
+
+; CHECK-DAG: %[[float:[0-9]+]] = OpTypeFloat 32
+; CHECK-DAG: %[[v4float:[0-9]+]] = OpTypeVector %[[float]] 4
+; CHECK-DAG: %[[image:[0-9]+]] = OpTypeImage %[[float]] 2D 2 1 0 1 Unknown
+; CHECK-DAG: %[[sampled_image:[0-9]+]] = OpTypeSampledImage %[[image]]
+; CHECK-DAG: %[[sampler:[0-9]+]] = OpTypeSampler
+; CHECK-DAG: %[[v3float:[0-9]+]] = OpTypeVector %[[float]] 3
+; CHECK-DAG: %[[int:[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: %[[v2int:[0-9]+]] = OpTypeVector %[[int]] 2
+; CHECK-DAG: %[[coord:[0-9]+]] = OpConstantComposite %[[v3float]]
+; CHECK-DAG: %[[component0:[0-9]+]] = OpConstant %[[int]] 0
+; CHECK-DAG: %[[const1:[0-9]+]] = OpConstant %[[int]] 1
+; CHECK-DAG: %[[offset:[0-9]+]] = OpConstantComposite %[[v2int]] %[[const1]] %[[const1]]
+
+ at .str = private unnamed_addr constant [4 x i8] c"img\00", align 1
+ at .str.1 = private unnamed_addr constant [5 x i8] c"samp\00", align 1
+
+define void @main() {
+entry:
+ %img = tail call target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32 0, i32 0, i32 1, i32 0, ptr @.str)
+ %sampler = tail call target("spirv.Sampler") @llvm.spv.resource.handlefrombinding.tspirv.Samplert(i32 0, i32 1, i32 1, i32 0, ptr @.str.1)
+
+; CHECK-DAG: %[[img_val:[0-9]+]] = OpLoad %[[image]] %[[image_var:[0-9]+]]
+; CHECK-DAG: %[[sampler_val:[0-9]+]] = OpLoad %[[sampler]] %[[sampler_var:[0-9]+]]
+; CHECK: %[[si:[0-9]+]] = OpSampledImage %[[sampled_image]] %[[img_val]] %[[sampler_val]]
+; CHECK: %[[res0:[0-9]+]] = OpImageGather %[[v4float]] %[[si]] %[[coord]] %[[component0]]
+ %res0 = call <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, target("spirv.Sampler") %sampler, <3 x float> zeroinitializer, i32 0, <2 x i32> zeroinitializer)
+
+; CHECK: %[[img_val2:[0-9]+]] = OpLoad %[[image]] %[[image_var]]
+; CHECK: %[[sampler_val2:[0-9]+]] = OpLoad %[[sampler]] %[[sampler_var]]
+; CHECK: %[[si2:[0-9]+]] = OpSampledImage %[[sampled_image]] %[[img_val2]] %[[sampler_val2]]
+; CHECK: %[[res1:[0-9]+]] = OpImageGather %[[v4float]] %[[si2]] %[[coord]] %[[const1]] ConstOffset %[[offset]]
+ %res1 = call <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, target("spirv.Sampler") %sampler, <3 x float> zeroinitializer, i32 1, <2 x i32> <i32 1, i32 1>)
+
+ ret void
+}
+
+declare target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Sampler") @llvm.spv.resource.handlefrombinding.tspirv.Samplert(i32, i32, i32, i32, ptr)
+declare <4 x float> @llvm.spv.resource.gather.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0), target("spirv.Sampler"), <3 x float>, i32, <2 x i32>)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/LoadLevel2DArray.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/LoadLevel2DArray.ll
new file mode 100644
index 0000000000000..9f2cc2c3cfefd
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/LoadLevel2DArray.ll
@@ -0,0 +1,41 @@
+; RUN: llc -O0 -mtriple=spirv1.6-vulkan1.3-compute %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-vulkan1.3-compute %s -o - -filetype=obj | spirv-val --allow-offset-texture-operand --target-env vulkan1.3 %}
+
+; CHECK-DAG: OpCapability Shader
+
+; CHECK-DAG: %[[float:[0-9]+]] = OpTypeFloat 32
+; CHECK-DAG: %[[v4float:[0-9]+]] = OpTypeVector %[[float]] 4
+; CHECK-DAG: %[[uint:[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: %[[v2uint:[0-9]+]] = OpTypeVector %[[uint]] 2
+; CHECK-DAG: %[[v3uint:[0-9]+]] = OpTypeVector %[[uint]] 3
+; CHECK-DAG: %[[image_2darray:[0-9]+]] = OpTypeImage %[[float]] 2D 2 1 0 1 Unknown
+
+; CHECK-DAG: %[[lod0:[0-9]+]] = OpConstant %[[uint]] 0
+; CHECK-DAG: %[[uint_1:[0-9]+]] = OpConstant %[[uint]] 1
+; CHECK-DAG: %[[coord_2darray:[0-9]+]] = OpConstantNull %[[v3uint]]
+; CHECK-DAG: %[[offset_2d:[0-9]+]] = OpConstantComposite %[[v2uint]] %[[uint_1]] %[[uint_1]]
+
+ at .str = private unnamed_addr constant [6 x i8] c"img2d\00", align 1
+
+define void @test_load_2darray() #0 {
+entry:
+ %img = tail call target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32 0, i32 0, i32 1, i32 0, ptr @.str)
+; CHECK: %[[img_val_2darray:[0-9]+]] = OpLoad %[[image_2darray]]
+; CHECK: %[[res_2darray:[0-9]+]] = OpImageFetch %[[v4float]] %[[img_val_2darray]] %[[coord_2darray]] Lod %[[lod0]]
+ %res = call <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, <3 x i32> zeroinitializer, i32 0, <2 x i32> zeroinitializer)
+ ret void
+}
+
+define void @test_load_2darray_offset() #0 {
+entry:
+ %img = tail call target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32 0, i32 0, i32 1, i32 0, ptr @.str)
+; CHECK: %[[img_val_2darray_off:[0-9]+]] = OpLoad %[[image_2darray]]
+; CHECK: %[[res_2darray_off:[0-9]+]] = OpImageFetch %[[v4float]] %[[img_val_2darray_off]] %[[coord_2darray]] Lod|ConstOffset %[[lod0]] %[[offset_2d]]
+ %res = call <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, <3 x i32> zeroinitializer, i32 0, <2 x i32> <i32 1, i32 1>)
+ ret void
+}
+
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+declare target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32, i32, i32, i32, ptr)
+declare <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.v3i32.i32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0), <3 x i32>, i32, <2 x i32>)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/Sample2DArray.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/Sample2DArray.ll
new file mode 100644
index 0000000000000..0e06caf4fd544
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/Sample2DArray.ll
@@ -0,0 +1,68 @@
+; RUN: llc -O0 -mtriple=spirv-vulkan-compute %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-compute %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: OpCapability Shader
+
+; CHECK-DAG: %[[float:[0-9]+]] = OpTypeFloat 32
+; CHECK-DAG: %[[v4float:[0-9]+]] = OpTypeVector %[[float]] 4
+; CHECK-DAG: %[[image:[0-9]+]] = OpTypeImage %[[float]] 2D 2 1 0 1 Unknown
+; CHECK-DAG: %[[sampled_image:[0-9]+]] = OpTypeSampledImage %[[image]]
+; CHECK-DAG: %[[sampler:[0-9]+]] = OpTypeSampler
+; CHECK-DAG: %[[v3float:[0-9]+]] = OpTypeVector %[[float]] 3
+; CHECK-DAG: %[[v2int:[0-9]+]] = OpTypeVector %[[int:[0-9]+]] 2
+; CHECK-DAG: %[[coord0:[0-9]+]] = OpConstantNull %[[v3float]]
+; CHECK-DAG: %[[coord1_val:[0-9]+]] = OpConstant %[[float]] 0.5
+; CHECK-DAG: %[[coord1:[0-9]+]] = OpConstantComposite %[[v3float]] %[[coord1_val]] %[[coord1_val]] %[[float0:[0-9]+]]
+; CHECK-DAG: %[[offset1_val:[0-9]+]] = OpConstant %[[int]] 1
+; CHECK-DAG: %[[offset1:[0-9]+]] = OpConstantComposite %[[v2int]] %[[offset1_val]] %[[offset1_val]]
+; CHECK-DAG: %[[bias:[0-9]+]] = OpConstant %[[float]] 2
+
+ at .str = private unnamed_addr constant [4 x i8] c"img\00", align 1
+ at .str.1 = private unnamed_addr constant [5 x i8] c"samp\00", align 1
+ at .str.2 = private unnamed_addr constant [4 x i8] c"out\00", align 1
+
+define void @main() {
+entry:
+ %img = tail call target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32 0, i32 0, i32 1, i32 0, ptr @.str)
+ %sampler = tail call target("spirv.Sampler") @llvm.spv.resource.handlefrombinding.tspirv.Samplert(i32 0, i32 1, i32 1, i32 0, ptr @.str.1)
+
+; CHECK: %[[img_val:[0-9]+]] = OpLoad %[[image]]
+; CHECK: %[[sampler_val:[0-9]+]] = OpLoad %[[sampler]]
+; CHECK: %[[si:[0-9]+]] = OpSampledImage %[[sampled_image]] %[[img_val]] %[[sampler_val]]
+; CHECK: %[[res0:[0-9]+]] = OpImageSampleImplicitLod %[[v4float]] %[[si]] %[[coord0]]{{[ ]*$}}
+ %res0 = call <4 x float> @llvm.spv.resource.sample.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, target("spirv.Sampler") %sampler, <3 x float> <float 0.0, float 0.0, float 0.0>, <2 x i32> zeroinitializer)
+
+; CHECK: %[[img_val2:[0-9]+]] = OpLoad %[[image]]
+; CHECK: %[[sampler_val2:[0-9]+]] = OpLoad %[[sampler]]
+; CHECK: %[[si2:[0-9]+]] = OpSampledImage %[[sampled_image]] %[[img_val2]] %[[sampler_val2]]
+; CHECK: %[[res1:[0-9]+]] = OpImageSampleImplicitLod %[[v4float]] %[[si2]] %[[coord1]] ConstOffset %[[offset1]]{{[ ]*$}}
+ %res1 = call <4 x float> @llvm.spv.resource.sample.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, target("spirv.Sampler") %sampler, <3 x float> <float 0.5, float 0.5, float 1.0>, <2 x i32> <i32 1, i32 1>)
+
+; CHECK: %[[img_val3:[0-9]+]] = OpLoad %[[image]]
+; CHECK: %[[sampler_val3:[0-9]+]] = OpLoad %[[sampler]]
+; CHECK: %[[si3:[0-9]+]] = OpSampledImage %[[sampled_image]] %[[img_val3]] %[[sampler_val3]]
+; CHECK: %[[res2:[0-9]+]] = OpImageSampleImplicitLod %[[v4float]] %[[si3]] %[[coord0]] Bias %[[bias]]{{[ ]*$}}
+ %res2 = call <4 x float> @llvm.spv.resource.samplebias.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, target("spirv.Sampler") %sampler, <3 x float> <float 0.0, float 0.0, float 0.0>, float 2.0, <2 x i32> zeroinitializer)
+
+; CHECK: %[[img_val4:[0-9]+]] = OpLoad %[[image]]
+; CHECK: %[[sampler_val4:[0-9]+]] = OpLoad %[[sampler]]
+; CHECK: %[[si4:[0-9]+]] = OpSampledImage %[[sampled_image]] %[[img_val4]] %[[sampler_val4]]
+; CHECK: %[[res3:[0-9]+]] = OpImageSampleImplicitLod %[[v4float]] %[[si4]] %[[coord1]] Bias|ConstOffset %[[bias]] %[[offset1]]{{[ ]*$}}
+ %res3 = call <4 x float> @llvm.spv.resource.samplebias.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, target("spirv.Sampler") %sampler, <3 x float> <float 0.5, float 0.5, float 1.0>, float 2.0, <2 x i32> <i32 1, i32 1>)
+
+ %tmp0 = fadd <4 x float> %res0, %res1
+ %tmp1 = fadd <4 x float> %res2, %res3
+ %res = fadd <4 x float> %tmp0, %tmp1
+
+ %out = tail call target("spirv.Image", float, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_1t(i32 0, i32 2, i32 1, i32 0, ptr @.str.2)
+ %out_ptr = call ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_f32_5_2_0_0_2_1t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %out, i32 0)
+ store <4 x float> %res, ptr addrspace(11) %out_ptr
+ ret void
+}
+
+declare target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Sampler") @llvm.spv.resource.handlefrombinding.tspirv.Samplert(i32, i32, i32, i32, ptr)
+declare <4 x float> @llvm.spv.resource.sample.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0), target("spirv.Sampler"), <3 x float>, <2 x i32>)
+declare <4 x float> @llvm.spv.resource.samplebias.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0), target("spirv.Sampler"), <3 x float>, float, <2 x i32>)
+declare target("spirv.Image", float, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_1t(i32, i32, i32, i32, ptr)
+declare ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_f32_5_2_0_0_2_1t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1), i32)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/SampleGrad2DArray.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/SampleGrad2DArray.ll
new file mode 100644
index 0000000000000..498d37bdb8787
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/SampleGrad2DArray.ll
@@ -0,0 +1,53 @@
+; RUN: llc -O0 -mtriple=spirv-vulkan-compute %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-compute %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: OpCapability Shader
+
+; CHECK-DAG: %[[float:[0-9]+]] = OpTypeFloat 32
+; CHECK-DAG: %[[v4float:[0-9]+]] = OpTypeVector %[[float]] 4
+; CHECK-DAG: %[[image:[0-9]+]] = OpTypeImage %[[float]] 2D 2 1 0 1 Unknown
+; CHECK-DAG: %[[sampled_image:[0-9]+]] = OpTypeSampledImage %[[image]]
+; CHECK-DAG: %[[sampler:[0-9]+]] = OpTypeSampler
+; CHECK-DAG: %[[v3float:[0-9]+]] = OpTypeVector %[[float]] 3
+; CHECK-DAG: %[[v2float:[0-9]+]] = OpTypeVector %[[float]] 2
+; CHECK-DAG: %[[v2int:[0-9]+]] = OpTypeVector %[[int:[0-9]+]] 2
+; CHECK-DAG: %[[coord0:[0-9]+]] = OpConstantNull %[[v3float]]
+; CHECK-DAG: %[[ddx:[0-9]+]] = OpConstantComposite %[[v2float]] %[[float_val:[0-9]+]] %[[float_val]]
+; CHECK-DAG: %[[ddy:[0-9]+]] = OpConstantComposite %[[v2float]] %[[float_val2:[0-9]+]] %[[float_val2]]
+; CHECK-DAG: %[[offset1_val:[0-9]+]] = OpConstant %[[int]] 1
+; CHECK-DAG: %[[offset1:[0-9]+]] = OpConstantComposite %[[v2int]] %[[offset1_val]] %[[offset1_val]]
+
+ at .str = private unnamed_addr constant [4 x i8] c"img\00", align 1
+ at .str.1 = private unnamed_addr constant [5 x i8] c"samp\00", align 1
+ at .str.2 = private unnamed_addr constant [4 x i8] c"out\00", align 1
+
+define void @main() {
+entry:
+ %img = tail call target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32 0, i32 0, i32 1, i32 0, ptr @.str)
+ %sampler = tail call target("spirv.Sampler") @llvm.spv.resource.handlefrombinding.tspirv.Samplert(i32 0, i32 1, i32 1, i32 0, ptr @.str.1)
+
+; CHECK: %[[img_val:[0-9]+]] = OpLoad %[[image]]
+; CHECK: %[[sampler_val:[0-9]+]] = OpLoad %[[sampler]]
+; CHECK: %[[si:[0-9]+]] = OpSampledImage %[[sampled_image]] %[[img_val]] %[[sampler_val]]
+; CHECK: %[[res0:[0-9]+]] = OpImageSampleExplicitLod %[[v4float]] %[[si]] %[[coord0]] Grad %[[ddx]] %[[ddy]]{{[ ]*$}}
+ %res0 = call <4 x float> @llvm.spv.resource.samplegrad.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, target("spirv.Sampler") %sampler, <3 x float> <float 0.0, float 0.0, float 0.0>, <2 x float> <float 0.5, float 0.5>, <2 x float> <float 0.25, float 0.25>, <2 x i32> zeroinitializer)
+
+; CHECK: %[[img_val2:[0-9]+]] = OpLoad %[[image]]
+; CHECK: %[[sampler_val2:[0-9]+]] = OpLoad %[[sampler]]
+; CHECK: %[[si2:[0-9]+]] = OpSampledImage %[[sampled_image]] %[[img_val2]] %[[sampler_val2]]
+; CHECK: %[[res1:[0-9]+]] = OpImageSampleExplicitLod %[[v4float]] %[[si2]] %[[coord1:[0-9]+]] Grad|ConstOffset %[[ddx]] %[[ddy]] %[[offset1]]{{[ ]*$}}
+ %res1 = call <4 x float> @llvm.spv.resource.samplegrad.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0) %img, target("spirv.Sampler") %sampler, <3 x float> <float 0.5, float 0.5, float 1.0>, <2 x float> <float 0.5, float 0.5>, <2 x float> <float 0.25, float 0.25>, <2 x i32> <i32 1, i32 1>)
+
+ %res = fadd <4 x float> %res0, %res1
+
+ %out = tail call target("spirv.Image", float, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_1t(i32 0, i32 2, i32 1, i32 0, ptr @.str.2)
+ %out_ptr = call ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_f32_5_2_0_0_2_1t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %out, i32 0)
+ store <4 x float> %res, ptr addrspace(11) %out_ptr
+ ret void
+}
+
+declare target("spirv.Image", float, 1, 2, 1, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_0_1_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Sampler") @llvm.spv.resource.handlefrombinding.tspirv.Samplert(i32, i32, i32, i32, ptr)
+declare <4 x float> @llvm.spv.resource.samplegrad.v4f32.tspirv.Image_f32_1_2_1_0_1_0t.tspirv.Samplert.v3f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 1, 0, 1, 0), target("spirv.Sampler"), <3 x float>, <2 x float>, <2 x float>, <2 x i32>)
+declare target("spirv.Image", float, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_1t(i32, i32, i32, i32, ptr)
+declare ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_f32_5_2_0_0_2_1t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1), i32)
More information about the cfe-commits
mailing list