Author: Steven Perron Date: 2026-02-11T09:12:22-05:00 New Revision: 3f73f839e2044b57adfaf0ada7b7dcedc54fcc0f
URL: https://github.com/llvm/llvm-project/commit/3f73f839e2044b57adfaf0ada7b7dcedc54fcc0f DIFF: https://github.com/llvm/llvm-project/commit/3f73f839e2044b57adfaf0ada7b7dcedc54fcc0f.diff LOG: [HLSL] Implement Sample* methods for Texture2D (#179322) This commit implement the methods: - SampleBias - SampleCmp - SampleCmpLevelZero - SampleGrad - SampleLevel They are added to the Texture2D resource type. All overloads except for those with the `status` argument. Part of https://github.com/llvm/llvm-project/issues/175630 Assisted-by: Gemini --------- Co-authored-by: Helena Kotas <[email protected]> Added: clang/test/CodeGenHLSL/resources/Texture2D-Sample.hlsl clang/test/CodeGenHLSL/resources/Texture2D-SampleBias.hlsl clang/test/CodeGenHLSL/resources/Texture2D-SampleCmp.hlsl clang/test/CodeGenHLSL/resources/Texture2D-SampleCmpLevelZero.hlsl clang/test/CodeGenHLSL/resources/Texture2D-SampleGrad.hlsl clang/test/CodeGenHLSL/resources/Texture2D-SampleLevel.hlsl clang/test/SemaHLSL/Texture2D-SampleBias.hlsl clang/test/SemaHLSL/Texture2D-SampleCmp.hlsl clang/test/SemaHLSL/Texture2D-SampleCmpLevelZero.hlsl clang/test/SemaHLSL/Texture2D-SampleGrad.hlsl clang/test/SemaHLSL/Texture2D-SampleLevel.hlsl Modified: clang/include/clang/Basic/Builtins.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/CodeGen/CGHLSLBuiltins.cpp clang/lib/CodeGen/CGHLSLRuntime.h clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h clang/lib/Sema/HLSLExternalSemaSource.cpp clang/lib/Sema/SemaHLSL.cpp clang/test/AST/HLSL/Texture2D-AST.hlsl Removed: clang/test/CodeGenHLSL/resources/Texture2D.sample.hlsl ################################################################################ diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 05e3af4a0e96f..ed4ec10375e48 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -5024,6 +5024,36 @@ def HLSLResourceSample : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLResourceSampleBias : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_sample_bias"]; + let Attributes = [NoThrow]; + let Prototype = "void(...)"; +} + +def HLSLResourceSampleGrad : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_sample_grad"]; + let Attributes = [NoThrow]; + let Prototype = "void(...)"; +} + +def HLSLResourceSampleLevel : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_sample_level"]; + let Attributes = [NoThrow]; + let Prototype = "void(...)"; +} + +def HLSLResourceSampleCmp : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_sample_cmp"]; + let Attributes = [NoThrow]; + let Prototype = "void(...)"; +} + +def HLSLResourceSampleCmpLevelZero : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_sample_cmp_level_zero"]; + let Attributes = [NoThrow]; + let Prototype = "void(...)"; +} + def HLSLResourceUninitializedHandle : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_uninitializedhandle"]; let Attributes = [NoThrow]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f12677ac11600..887d1b5f2bbfd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13509,6 +13509,9 @@ def err_hlsl_assign_to_global_resource: Error< def err_hlsl_push_constant_unique : Error<"cannot have more than one push constant block">; +def err_hlsl_samplecmp_requires_float + : Error<"'SampleCmp' and 'SampleCmpLevelZero' require resource to contain " + "a floating point type">; // Layout randomization diagnostics. def err_non_designated_init_used : Error< diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index c72eef1982e9e..5c060598e4b39 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -414,6 +414,30 @@ static std::string getSpecConstantFunctionName(clang::QualType SpecConstantType, return Name; } +static Value *emitHlslOffset(CodeGenFunction &CGF, const CallExpr *E, + unsigned OffsetArgIndex) { + if (E->getNumArgs() > OffsetArgIndex) + return CGF.EmitScalarExpr(E->getArg(OffsetArgIndex)); + + llvm::Type *CoordTy = CGF.ConvertType(E->getArg(2)->getType()); + llvm::Type *Int32Ty = CGF.Int32Ty; + llvm::Type *OffsetTy = Int32Ty; + if (auto *VT = dyn_cast<llvm::FixedVectorType>(CoordTy)) + OffsetTy = llvm::FixedVectorType::get(Int32Ty, VT->getNumElements()); + return llvm::Constant::getNullValue(OffsetTy); +} + +static Value *emitHlslClamp(CodeGenFunction &CGF, const CallExpr *E, + unsigned ClampArgIndex) { + Value *Clamp = CGF.EmitScalarExpr(E->getArg(ClampArgIndex)); + // The builtin is defined with variadic arguments, so the clamp parameter + // might have been promoted to double. The intrinsic requires a 32-bit + // float. + if (Clamp->getType() != CGF.Builder.getFloatTy()) + Clamp = CGF.Builder.CreateFPCast(Clamp, CGF.Builder.getFloatTy()); + return Clamp; +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -495,19 +519,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, Args.push_back(HandleOp); Args.push_back(SamplerOp); Args.push_back(CoordOp); - if (E->getNumArgs() > 3) { - Args.push_back(EmitScalarExpr(E->getArg(3))); - } else { - // Default offset is 0. - // We need to know the type of the offset. It should be a vector of i32 - // with the same number of elements as the coordinate, or scalar i32. - llvm::Type *CoordTy = CoordOp->getType(); - llvm::Type *Int32Ty = Builder.getInt32Ty(); - llvm::Type *OffsetTy = Int32Ty; - if (auto *VT = dyn_cast<llvm::FixedVectorType>(CoordTy)) - OffsetTy = llvm::FixedVectorType::get(Int32Ty, VT->getNumElements()); - Args.push_back(llvm::Constant::getNullValue(OffsetTy)); - } + Args.push_back(emitHlslOffset(*this, E, 3)); llvm::Type *RetTy = ConvertType(E->getType()); if (E->getNumArgs() <= 4) { @@ -515,16 +527,124 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, RetTy, CGM.getHLSLRuntime().getSampleIntrinsic(), Args); } - llvm::Value *Clamp = EmitScalarExpr(E->getArg(4)); - // The builtin is defined with variadic arguments, so the clamp parameter - // might have been promoted to double. The intrinsic requires a 32-bit - // float. - if (Clamp->getType() != Builder.getFloatTy()) - Clamp = Builder.CreateFPCast(Clamp, Builder.getFloatTy()); - Args.push_back(Clamp); + Args.push_back(emitHlslClamp(*this, E, 4)); return Builder.CreateIntrinsic( RetTy, CGM.getHLSLRuntime().getSampleClampIntrinsic(), Args); } + case Builtin::BI__builtin_hlsl_resource_sample_bias: { + Value *HandleOp = EmitScalarExpr(E->getArg(0)); + Value *SamplerOp = EmitScalarExpr(E->getArg(1)); + Value *CoordOp = EmitScalarExpr(E->getArg(2)); + Value *BiasOp = EmitScalarExpr(E->getArg(3)); + if (BiasOp->getType() != Builder.getFloatTy()) + BiasOp = Builder.CreateFPCast(BiasOp, Builder.getFloatTy()); + + SmallVector<Value *, 6> Args; // Max 6 arguments for SampleBias + Args.push_back(HandleOp); + Args.push_back(SamplerOp); + Args.push_back(CoordOp); + Args.push_back(BiasOp); + Args.push_back(emitHlslOffset(*this, E, 4)); + + llvm::Type *RetTy = ConvertType(E->getType()); + if (E->getNumArgs() <= 5) + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getSampleBiasIntrinsic(), Args); + + Args.push_back(emitHlslClamp(*this, E, 5)); + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getSampleBiasClampIntrinsic(), Args); + } + case Builtin::BI__builtin_hlsl_resource_sample_grad: { + Value *HandleOp = EmitScalarExpr(E->getArg(0)); + Value *SamplerOp = EmitScalarExpr(E->getArg(1)); + Value *CoordOp = EmitScalarExpr(E->getArg(2)); + Value *DDXOp = EmitScalarExpr(E->getArg(3)); + Value *DDYOp = EmitScalarExpr(E->getArg(4)); + + SmallVector<Value *, 7> Args; + Args.push_back(HandleOp); + Args.push_back(SamplerOp); + Args.push_back(CoordOp); + Args.push_back(DDXOp); + Args.push_back(DDYOp); + Args.push_back(emitHlslOffset(*this, E, 5)); + + llvm::Type *RetTy = ConvertType(E->getType()); + + if (E->getNumArgs() <= 6) { + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getSampleGradIntrinsic(), Args); + } + + Args.push_back(emitHlslClamp(*this, E, 6)); + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getSampleGradClampIntrinsic(), Args); + } + case Builtin::BI__builtin_hlsl_resource_sample_level: { + Value *HandleOp = EmitScalarExpr(E->getArg(0)); + Value *SamplerOp = EmitScalarExpr(E->getArg(1)); + Value *CoordOp = EmitScalarExpr(E->getArg(2)); + Value *LODOp = EmitScalarExpr(E->getArg(3)); + if (LODOp->getType() != Builder.getFloatTy()) + LODOp = Builder.CreateFPCast(LODOp, Builder.getFloatTy()); + + SmallVector<Value *, 5> Args; // Max 5 arguments for SampleLevel + Args.push_back(HandleOp); + Args.push_back(SamplerOp); + Args.push_back(CoordOp); + Args.push_back(LODOp); + Args.push_back(emitHlslOffset(*this, E, 4)); + + llvm::Type *RetTy = ConvertType(E->getType()); + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getSampleLevelIntrinsic(), Args); + } + case Builtin::BI__builtin_hlsl_resource_sample_cmp: { + Value *HandleOp = EmitScalarExpr(E->getArg(0)); + Value *SamplerOp = EmitScalarExpr(E->getArg(1)); + Value *CoordOp = EmitScalarExpr(E->getArg(2)); + Value *CmpOp = EmitScalarExpr(E->getArg(3)); + if (CmpOp->getType() != Builder.getFloatTy()) + CmpOp = Builder.CreateFPCast(CmpOp, Builder.getFloatTy()); + + SmallVector<Value *, 6> Args; // Max 6 arguments for SampleCmp + Args.push_back(HandleOp); + Args.push_back(SamplerOp); + Args.push_back(CoordOp); + Args.push_back(CmpOp); + Args.push_back(emitHlslOffset(*this, E, 4)); + + llvm::Type *RetTy = ConvertType(E->getType()); + if (E->getNumArgs() <= 5) { + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getSampleCmpIntrinsic(), Args); + } + + Args.push_back(emitHlslClamp(*this, E, 5)); + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getSampleCmpClampIntrinsic(), Args); + } + case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero: { + Value *HandleOp = EmitScalarExpr(E->getArg(0)); + Value *SamplerOp = EmitScalarExpr(E->getArg(1)); + Value *CoordOp = EmitScalarExpr(E->getArg(2)); + Value *CmpOp = EmitScalarExpr(E->getArg(3)); + if (CmpOp->getType() != Builder.getFloatTy()) + CmpOp = Builder.CreateFPCast(CmpOp, Builder.getFloatTy()); + + SmallVector<Value *, 5> Args; + Args.push_back(HandleOp); + Args.push_back(SamplerOp); + Args.push_back(CoordOp); + Args.push_back(CmpOp); + + Args.push_back(emitHlslOffset(*this, E, 4)); + + llvm::Type *RetTy = ConvertType(E->getType()); + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getSampleCmpLevelZeroIntrinsic(), Args); + } case Builtin::BI__builtin_hlsl_resource_load_with_status: case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: { Value *HandleOp = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index c13f91afa6a39..62349c9dea7eb 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -165,6 +165,15 @@ class CGHLSLRuntime { resource_getpointer) GENERATE_HLSL_INTRINSIC_FUNCTION(Sample, resource_sample) GENERATE_HLSL_INTRINSIC_FUNCTION(SampleClamp, resource_sample_clamp) + GENERATE_HLSL_INTRINSIC_FUNCTION(SampleBias, resource_samplebias) + GENERATE_HLSL_INTRINSIC_FUNCTION(SampleBiasClamp, resource_samplebias_clamp) + GENERATE_HLSL_INTRINSIC_FUNCTION(SampleGrad, resource_samplegrad) + GENERATE_HLSL_INTRINSIC_FUNCTION(SampleGradClamp, resource_samplegrad_clamp) + GENERATE_HLSL_INTRINSIC_FUNCTION(SampleLevel, resource_samplelevel) + GENERATE_HLSL_INTRINSIC_FUNCTION(SampleCmp, resource_samplecmp) + GENERATE_HLSL_INTRINSIC_FUNCTION(SampleCmpClamp, resource_samplecmp_clamp) + GENERATE_HLSL_INTRINSIC_FUNCTION(SampleCmpLevelZero, + resource_samplecmplevelzero) GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, resource_handlefrombinding) GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromImplicitBinding, diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 1dd7fd6fac455..4ef54cf49412f 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -1303,21 +1303,15 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() { BuiltinTypeDeclBuilder & BuiltinTypeDeclBuilder::addSampleMethods(ResourceDimension Dim) { assert(!Record->isCompleteDefinition() && "record is already complete"); - ASTContext &AST = Record->getASTContext(); QualType ReturnType = getFirstTemplateTypeParam(); - QualType SamplerStateType = lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext()); - uint32_t VecSize = getResourceDimensions(Dim); - QualType FloatTy = AST.FloatTy; QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize); - QualType IntTy = AST.IntTy; QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize); - using PH = BuiltinTypeMethodBuilder::PlaceHolder; // T Sample(SamplerState s, float2 location) @@ -1354,6 +1348,246 @@ BuiltinTypeDeclBuilder::addSampleMethods(ResourceDimension Dim) { .finalize(); } +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addSampleBiasMethods(ResourceDimension Dim) { + assert(!Record->isCompleteDefinition() && "record is already complete"); + ASTContext &AST = Record->getASTContext(); + QualType ReturnType = getFirstTemplateTypeParam(); + QualType SamplerStateType = + lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext()); + uint32_t VecSize = getResourceDimensions(Dim); + QualType FloatTy = AST.FloatTy; + QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize); + QualType IntTy = AST.IntTy; + QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize); + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + + // T SampleBias(SamplerState s, float2 location, float bias) + BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType) + .addParam("Sampler", SamplerStateType) + .addParam("Location", Float2Ty) + .addParam("Bias", FloatTy) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2) + .returnValue(PH::LastStmt) + .finalize(); + + // T SampleBias(SamplerState s, float2 location, float bias, int2 offset) + BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType) + .addParam("Sampler", SamplerStateType) + .addParam("Location", Float2Ty) + .addParam("Bias", FloatTy) + .addParam("Offset", Int2Ty) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3) + .returnValue(PH::LastStmt) + .finalize(); + + // T SampleBias(SamplerState s, float2 location, float bias, int2 offset, + // float clamp) + return BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType) + .addParam("Sampler", SamplerStateType) + .addParam("Location", Float2Ty) + .addParam("Bias", FloatTy) + .addParam("Offset", Int2Ty) + .addParam("Clamp", FloatTy) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4) + .returnValue(PH::LastStmt) + .finalize(); +} + +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addSampleGradMethods(ResourceDimension Dim) { + assert(!Record->isCompleteDefinition() && "record is already complete"); + ASTContext &AST = Record->getASTContext(); + QualType ReturnType = getFirstTemplateTypeParam(); + QualType SamplerStateType = + lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext()); + uint32_t VecSize = getResourceDimensions(Dim); + QualType FloatTy = AST.FloatTy; + QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize); + QualType IntTy = AST.IntTy; + QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize); + 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) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3) + .returnValue(PH::LastStmt) + .finalize(); + + // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy, + // int2 offset) + BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType) + .addParam("Sampler", SamplerStateType) + .addParam("Location", Float2Ty) + .addParam("DDX", Float2Ty) + .addParam("DDY", Float2Ty) + .addParam("Offset", Int2Ty) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4) + .returnValue(PH::LastStmt) + .finalize(); + + // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy, + // 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("Clamp", FloatTy) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4, + PH::_5) + .returnValue(PH::LastStmt) + .finalize(); +} + +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addSampleLevelMethods(ResourceDimension Dim) { + assert(!Record->isCompleteDefinition() && "record is already complete"); + ASTContext &AST = Record->getASTContext(); + QualType ReturnType = getFirstTemplateTypeParam(); + QualType SamplerStateType = + lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext()); + uint32_t VecSize = getResourceDimensions(Dim); + QualType FloatTy = AST.FloatTy; + QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize); + QualType IntTy = AST.IntTy; + QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize); + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + + // T SampleLevel(SamplerState s, float2 location, float lod) + BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType) + .addParam("Sampler", SamplerStateType) + .addParam("Location", Float2Ty) + .addParam("LOD", FloatTy) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2) + .returnValue(PH::LastStmt) + .finalize(); + + // T SampleLevel(SamplerState s, float2 location, float lod, int2 offset) + return BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType) + .addParam("Sampler", SamplerStateType) + .addParam("Location", Float2Ty) + .addParam("LOD", FloatTy) + .addParam("Offset", Int2Ty) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3) + .returnValue(PH::LastStmt) + .finalize(); +} + +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addSampleCmpMethods(ResourceDimension Dim) { + 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); + QualType FloatTy = AST.FloatTy; + QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize); + QualType IntTy = AST.IntTy; + QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize); + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + + // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value) + BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType) + .addParam("Sampler", SamplerComparisonStateType) + .addParam("Location", Float2Ty) + .addParam("CompareValue", FloatTy) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle, + PH::LastStmt, PH::_1, PH::_2) + .returnValue(PH::LastStmt) + .finalize(); + + // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value, + // int2 offset) + BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType) + .addParam("Sampler", SamplerComparisonStateType) + .addParam("Location", Float2Ty) + .addParam("CompareValue", FloatTy) + .addParam("Offset", Int2Ty) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle, + PH::LastStmt, PH::_1, PH::_2, PH::_3) + .returnValue(PH::LastStmt) + .finalize(); + + // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value, + // int2 offset, float clamp) + return BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType) + .addParam("Sampler", SamplerComparisonStateType) + .addParam("Location", Float2Ty) + .addParam("CompareValue", FloatTy) + .addParam("Offset", Int2Ty) + .addParam("Clamp", FloatTy) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle, + PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4) + .returnValue(PH::LastStmt) + .finalize(); +} + +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addSampleCmpLevelZeroMethods(ResourceDimension Dim) { + 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); + QualType FloatTy = AST.FloatTy; + QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize); + QualType IntTy = AST.IntTy; + QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize); + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + + // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float + // compare_value) + BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType) + .addParam("Sampler", SamplerComparisonStateType) + .addParam("Location", Float2Ty) + .addParam("CompareValue", FloatTy) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2) + .returnValue(PH::LastStmt) + .finalize(); + + // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float + // compare_value, int2 offset) + return BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType) + .addParam("Sampler", SamplerComparisonStateType) + .addParam("Location", Float2Ty) + .addParam("CompareValue", FloatTy) + .addParam("Offset", Int2Ty) + .accessHandleFieldOnResource(PH::_0) + .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType, + PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3) + .returnValue(PH::LastStmt) + .finalize(); +} + FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const { auto I = Fields.find("__handle"); assert(I != Fields.end() && diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h index aa6967e1eb725..fcb61731c5416 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h @@ -95,6 +95,11 @@ class BuiltinTypeDeclBuilder { 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 &addIncrementCounterMethod(); BuiltinTypeDeclBuilder &addDecrementCounterMethod(); BuiltinTypeDeclBuilder &addHandleAccessFunction(DeclarationName &Name, diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index f7862b3a3f594..662627901539a 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -260,7 +260,12 @@ static BuiltinTypeDeclBuilder setupTextureType(CXXRecordDecl *Decl, Sema &S, .addCopyConstructor() .addCopyAssignmentOperator() .addStaticInitializationFunctions(false) - .addSampleMethods(Dim); + .addSampleMethods(Dim) + .addSampleBiasMethods(Dim) + .addSampleGradMethods(Dim) + .addSampleLevelMethods(Dim) + .addSampleCmpMethods(Dim) + .addSampleCmpLevelZeroMethods(Dim); } // This function is responsible for constructing the constraint expression for diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 813ab16fece73..4271056ad43cc 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -3324,6 +3324,127 @@ static bool CheckVectorElementCount(Sema *S, QualType PassedType, return false; } +enum class SampleKind { Sample, Bias, Grad, Level, Cmp, CmpLevelZero }; + +static bool CheckSamplingBuiltin(Sema &S, CallExpr *TheCall, SampleKind Kind) { + unsigned MinArgs, MaxArgs; + if (Kind == SampleKind::Sample) { + MinArgs = 3; + MaxArgs = 5; + } else if (Kind == SampleKind::Bias) { + MinArgs = 4; + MaxArgs = 6; + } else if (Kind == SampleKind::Grad) { + MinArgs = 5; + MaxArgs = 7; + } else if (Kind == SampleKind::Level) { + MinArgs = 4; + MaxArgs = 5; + } else if (Kind == SampleKind::Cmp) { + MinArgs = 4; + MaxArgs = 6; + } else { + assert(Kind == SampleKind::CmpLevelZero); + MinArgs = 4; + MaxArgs = 5; + } + + if (S.checkArgCountRange(TheCall, MinArgs, MaxArgs)) + return true; + + // Check the texture handle. + if (CheckResourceHandle(&S, TheCall, 0, + [](const HLSLAttributedResourceType *ResType) { + return ResType->getAttrs().ResourceDimension == + llvm::dxil::ResourceDimension::Unknown; + })) + return true; + + // Check the sampler handle. + if (CheckResourceHandle(&S, TheCall, 1, + [](const HLSLAttributedResourceType *ResType) { + return ResType->getAttrs().ResourceClass != + llvm::hlsl::ResourceClass::Sampler; + })) + return true; + + auto *ResourceTy = + TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>(); + + // Check the location. + unsigned ExpectedDim = + getResourceDimensions(ResourceTy->getAttrs().ResourceDimension); + if (CheckVectorElementCount(&S, TheCall->getArg(2)->getType(), + S.Context.FloatTy, ExpectedDim, + TheCall->getBeginLoc())) + return true; + + unsigned NextIdx = 3; + if (Kind == SampleKind::Bias || Kind == SampleKind::Level || + Kind == SampleKind::Cmp || Kind == SampleKind::CmpLevelZero) { + // Check the bias, lod level, or compare value, depending on the kind. + // All of them must be a scalar float value. + QualType BiasOrLODOrCmpTy = TheCall->getArg(NextIdx)->getType(); + if (!BiasOrLODOrCmpTy->isFloatingType() || + BiasOrLODOrCmpTy->isVectorType()) { + S.Diag(TheCall->getArg(NextIdx)->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << BiasOrLODOrCmpTy << S.Context.FloatTy << 1 << 0 << 0; + return true; + } + NextIdx++; + } else if (Kind == SampleKind::Grad) { + // Check the DDX operand. + if (CheckVectorElementCount(&S, TheCall->getArg(NextIdx)->getType(), + S.Context.FloatTy, ExpectedDim, + TheCall->getArg(NextIdx)->getBeginLoc())) + return true; + + // Check the DDY operand. + if (CheckVectorElementCount(&S, TheCall->getArg(NextIdx + 1)->getType(), + S.Context.FloatTy, ExpectedDim, + TheCall->getArg(NextIdx + 1)->getBeginLoc())) + return true; + NextIdx += 2; + } + + // Check the offset operand. + if (TheCall->getNumArgs() > NextIdx) { + if (CheckVectorElementCount(&S, TheCall->getArg(NextIdx)->getType(), + S.Context.IntTy, ExpectedDim, + TheCall->getArg(NextIdx)->getBeginLoc())) + return true; + NextIdx++; + } + + // Check the clamp operand. + if (Kind != SampleKind::Level && Kind != SampleKind::CmpLevelZero && + TheCall->getNumArgs() > NextIdx) { + QualType ClampTy = TheCall->getArg(NextIdx)->getType(); + if (!ClampTy->isFloatingType() || ClampTy->isVectorType()) { + S.Diag(TheCall->getArg(NextIdx)->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << ClampTy << S.Context.FloatTy << 1 << 0 << 0; + return true; + } + } + + assert(ResourceTy->hasContainedType() && + "Expecting a contained type for resource with a dimension " + "attribute."); + QualType ReturnType = ResourceTy->getContainedType(); + if (Kind == SampleKind::Cmp || Kind == SampleKind::CmpLevelZero) { + if (!ReturnType->hasFloatingRepresentation()) { + S.Diag(TheCall->getBeginLoc(), diag::err_hlsl_samplecmp_requires_float); + return true; + } + ReturnType = S.Context.FloatTy; + } + TheCall->setType(ReturnType); + + return false; +} + // Note: returning true in this case results in CheckBuiltinFunctionCall // returning an ExprError bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { @@ -3444,59 +3565,18 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } - case Builtin::BI__builtin_hlsl_resource_sample: { - if (SemaRef.checkArgCountRange(TheCall, 3, 5)) - return true; - - if (CheckResourceHandle(&SemaRef, TheCall, 0, - [](const HLSLAttributedResourceType *ResType) { - return ResType->getAttrs().ResourceDimension == - llvm::dxil::ResourceDimension::Unknown; - })) - return true; - - if (CheckResourceHandle(&SemaRef, TheCall, 1, - [](const HLSLAttributedResourceType *ResType) { - return ResType->getAttrs().ResourceClass != - llvm::hlsl::ResourceClass::Sampler; - })) - return true; - - auto *ResourceTy = - TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>(); - - unsigned ExpectedDim = - getResourceDimensions(ResourceTy->getAttrs().ResourceDimension); - if (CheckVectorElementCount(&SemaRef, TheCall->getArg(2)->getType(), - SemaRef.Context.FloatTy, ExpectedDim, - TheCall->getArg(2)->getBeginLoc())) - return true; - - if (TheCall->getNumArgs() > 3) { - if (CheckVectorElementCount(&SemaRef, TheCall->getArg(3)->getType(), - SemaRef.Context.IntTy, ExpectedDim, - TheCall->getArg(3)->getBeginLoc())) - return true; - } - - if (TheCall->getNumArgs() > 4) { - QualType ClampTy = TheCall->getArg(4)->getType(); - if (!ClampTy->isFloatingType() || ClampTy->isVectorType()) { - SemaRef.Diag(TheCall->getArg(4)->getBeginLoc(), - diag::err_typecheck_convert_incompatible) - << ClampTy << SemaRef.Context.FloatTy << 1 << 0 << 0; - return true; - } - } - - assert(ResourceTy->hasContainedType() && - "Expecting a contained type for resource with a dimension " - "attribute."); - QualType ReturnType = ResourceTy->getContainedType(); - TheCall->setType(ReturnType); - - break; - } + case Builtin::BI__builtin_hlsl_resource_sample: + return CheckSamplingBuiltin(SemaRef, TheCall, SampleKind::Sample); + case Builtin::BI__builtin_hlsl_resource_sample_bias: + return CheckSamplingBuiltin(SemaRef, TheCall, SampleKind::Bias); + case Builtin::BI__builtin_hlsl_resource_sample_grad: + return CheckSamplingBuiltin(SemaRef, TheCall, SampleKind::Grad); + case Builtin::BI__builtin_hlsl_resource_sample_level: + return CheckSamplingBuiltin(SemaRef, TheCall, SampleKind::Level); + case Builtin::BI__builtin_hlsl_resource_sample_cmp: + return CheckSamplingBuiltin(SemaRef, TheCall, SampleKind::Cmp); + case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero: + return CheckSamplingBuiltin(SemaRef, TheCall, SampleKind::CmpLevelZero); case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: { assert(TheCall->getNumArgs() == 1 && "expected 1 arg"); // Update return type to be the attributed resource type from arg0. diff --git a/clang/test/AST/HLSL/Texture2D-AST.hlsl b/clang/test/AST/HLSL/Texture2D-AST.hlsl index 95343712b72fa..abdf0a8b35ab7 100644 --- a/clang/test/AST/HLSL/Texture2D-AST.hlsl +++ b/clang/test/AST/HLSL/Texture2D-AST.hlsl @@ -5,6 +5,11 @@ // 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 {{.*}} Texture2D // CHECK: TemplateTypeParmDecl {{.*}} element_type // CHECK: CXXRecordDecl {{.*}} Texture2D definition @@ -83,11 +88,352 @@ // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Clamp' 'float' // CHECK-NEXT: AlwaysInlineAttr +// CHECK: CXXMethodDecl {{.*}} SampleBias 'element_type (hlsl::SamplerState, vector<float, 2>, float)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'Bias' 'float' +// CHECK-NEXT: AlwaysInlineAttr + +// CHECK: CXXMethodDecl {{.*}} SampleBias 'element_type (hlsl::SamplerState, vector<float, 2>, float, vector<int, 2>)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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: 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, 2>, float, vector<int, 2>, float)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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: 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, 2>, vector<float, 2>, vector<float, 2>)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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: 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, 2>, vector<float, 2>, vector<float, 2>, vector<int, 2>)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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: 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, 2>, vector<float, 2>, vector<float, 2>, vector<int, 2>, float)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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: 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, 2>, float)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'LOD' 'float' +// CHECK-NEXT: AlwaysInlineAttr + +// CHECK: CXXMethodDecl {{.*}} SampleLevel 'element_type (hlsl::SamplerState, vector<float, 2>, float, vector<int, 2>)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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: 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, 2>, float)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float' +// CHECK-NEXT: AlwaysInlineAttr + +// CHECK: CXXMethodDecl {{.*}} SampleCmp 'float (hlsl::SamplerComparisonState, vector<float, 2>, float, vector<int, 2>)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>' +// 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, 2>, float, vector<int, 2>, float)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>' +// 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, 2>, float)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float' +// CHECK-NEXT: AlwaysInlineAttr + +// CHECK: CXXMethodDecl {{.*}} SampleCmpLevelZero 'float (hlsl::SamplerComparisonState, vector<float, 2>, float, vector<int, 2>)' +// CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerComparisonState' +// CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector<float, 2>' +// 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::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D<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, 2>' lvalue ParmVar {{.*}} 'Location' 'vector<float, 2>' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'CompareValue' 'float' +// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>' lvalue ParmVar {{.*}} 'Offset' 'vector<int, 2>' +// CHECK-NEXT: AlwaysInlineAttr + Texture2D<float4> t; SamplerState s; +SamplerComparisonState scs; -void main(float2 loc) { +void main(float2 loc, float cmp) { t.Sample(s, loc); t.Sample(s, loc, int2(1, 2)); t.Sample(s, loc, int2(1, 2), 1.0); -} \ No newline at end of file + 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)); +} diff --git a/clang/test/CodeGenHLSL/resources/Texture2D.sample.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-Sample.hlsl similarity index 100% rename from clang/test/CodeGenHLSL/resources/Texture2D.sample.hlsl rename to clang/test/CodeGenHLSL/resources/Texture2D-Sample.hlsl diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-SampleBias.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleBias.hlsl new file mode 100644 index 0000000000000..c138e7f0a6c8b --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/Texture2D-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::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) } + +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") } + +Texture2D<float4> t; +SamplerState s; + +// CHECK-LABEL: @test_bias(float vector[2]) +// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00) +// CHECK: ret <4 x float> %[[CALL]] + +float4 test_bias(float2 loc : LOC) : SV_Target { + return t.SampleBias(s, loc, 0.0f); +} + +// CHECK-LABEL: define linkonce_odr {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[2], float)( +// CHECK: %[[THIS_VAL1:.*]] = load ptr, ptr %{{.*}} +// CHECK: %[[HANDLE_GEP1:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2D", 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <2 x float> %{{.*}}, float %[[BIAS_CAST1]], <2 x i32> zeroinitializer) +// SPIRV: %{{.*}} = call {{.*}} <4 x float> @llvm.spv.resource.samplebias.v4f32.tspirv.Image_f32_1_2_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <2 x float> %{{.*}}, float %[[BIAS_CAST1]], <2 x i32> zeroinitializer) + +// CHECK-LABEL: @test_offset(float vector[2]) +// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[2], float, int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>) +// CHECK: ret <4 x float> %[[CALL_OFFSET]] + +float4 test_offset(float2 loc : LOC) : SV_Target { + return t.SampleBias(s, loc, 0.0f, int2(1, 2)); +} + +// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[2], float, int vector[2])( +// CHECK: %[[THIS_VAL2:.*]] = load ptr, ptr %{{.*}} +// CHECK: %[[HANDLE_GEP2:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2D", 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <2 x float> %{{.*}}, float %[[BIAS_CAST2]], <2 x i32> %{{.*}}) +// SPIRV: %{{.*}} = call {{.*}} <4 x float> @llvm.spv.resource.samplebias.v4f32.tspirv.Image_f32_1_2_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <2 x float> %{{.*}}, float %[[BIAS_CAST2]], <2 x i32> %{{.*}}) + +// CHECK-LABEL: @test_clamp(float vector[2]) +// CHECK: %[[CALL_CLAMP:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[2], float, int vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 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(float2 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::Texture2D<float vector[4]>::SampleBias(hlsl::SamplerState, float vector[2], float, int vector[2], float)( +// CHECK: %[[THIS_VAL3:.*]] = load ptr, ptr %{{.*}} +// CHECK: %[[HANDLE_GEP3:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2D", 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE3]], target("dx.Sampler", 0) %[[SAMPLER_H3]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE3]], target("spirv.Sampler") %[[SAMPLER_H3]], <2 x float> %{{.*}}, float %[[BIAS_CAST3]], <2 x i32> %{{.*}}, float %[[CLAMP_CAST3]]) diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-SampleCmp.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleCmp.hlsl new file mode 100644 index 0000000000000..b76b02177abbc --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/Texture2D-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::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::SamplerComparisonState" = type { target("dx.Sampler", 0) } + +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::SamplerComparisonState" = type { target("spirv.Sampler") } + +Texture2D<float4> t; +SamplerComparisonState s; + +// CHECK-LABEL: @test_cmp(float vector[2], float) +// CHECK: %[[CALL:.*]] = call {{.*}} float @hlsl::Texture2D<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <2 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00) +// CHECK: ret float %[[CALL]] + +float test_cmp(float2 loc : LOC, float cmp : CMP) : SV_Target { + return t.SampleCmp(s, loc, 0.0f); +} + +// CHECK-LABEL: define linkonce_odr hidden {{.*}} float @hlsl::Texture2D<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[2], float)( +// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS1:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER1:[^,]+]], <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <2 x float> %[[COORD_VAL1]], float %[[CMP_CAST1]], <2 x i32> zeroinitializer) +// SPIRV: call {{.*}} float @llvm.spv.resource.samplecmp.f32.tspirv.Image_f32_1_2_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <2 x float> %[[COORD_VAL1]], float %[[CMP_CAST1]], <2 x i32> zeroinitializer) + +// CHECK-LABEL: @test_offset(float vector[2], float) +// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} float @hlsl::Texture2D<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[2], float, int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <2 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>) +// CHECK: ret float %[[CALL_OFFSET]] + +float test_offset(float2 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::Texture2D<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[2], float, int vector[2])( +// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS2:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER2:[^,]+]], <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <2 x float> %[[COORD_VAL2]], float %[[CMP_CAST2]], <2 x i32> %[[OFFSET_VAL2]]) + +// CHECK-LABEL: @test_clamp(float vector[2], float) +// CHECK: %[[CALL_CLAMP:.*]] = call {{.*}} float @hlsl::Texture2D<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[2], float, int vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <2 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(float2 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::Texture2D<float vector[4]>::SampleCmp(hlsl::SamplerComparisonState, float vector[2], float, int vector[2], float)( +// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS3:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER3:[^,]+]], <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE3]], target("dx.Sampler", 0) %[[SAMPLER_H3]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE3]], target("spirv.Sampler") %[[SAMPLER_H3]], <2 x float> %[[COORD_VAL3]], float %[[CMP_CAST3]], <2 x i32> %[[OFFSET_VAL3]], float %[[CLAMP_CAST3]]) diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-SampleCmpLevelZero.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleCmpLevelZero.hlsl new file mode 100644 index 0000000000000..224e9d3837374 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/Texture2D-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 + +Texture2D<float4> t; +SamplerComparisonState s; + +// CHECK-LABEL: @test_cmp_level_zero(float vector[2], float) +// CHECK: %[[CALL:.*]] = call {{.*}} float @hlsl::Texture2D<float vector[4]>::SampleCmpLevelZero(hlsl::SamplerComparisonState, float vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <2 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00) +// CHECK: ret float %[[CALL]] + +float test_cmp_level_zero(float2 loc : LOC, float cmp : CMP) : SV_Target { + return t.SampleCmpLevelZero(s, loc, 0.0f); +} + +// CHECK-LABEL: define linkonce_odr hidden {{.*}} float @hlsl::Texture2D<float vector[4]>::SampleCmpLevelZero(hlsl::SamplerComparisonState, float vector[2], float)( +// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS1:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER1:[^,]+]], <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <2 x float> %[[COORD_VAL1]], float %[[CMP_CAST1]], <2 x i32> zeroinitializer) +// SPIRV: call {{.*}} float @llvm.spv.resource.samplecmplevelzero.f32.tspirv.Image_f32_1_2_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <2 x float> %[[COORD_VAL1]], float %[[CMP_CAST1]], <2 x i32> zeroinitializer) + +// CHECK-LABEL: @test_cmp_level_zero_offset(float vector[2], float) +// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} float @hlsl::Texture2D<float vector[4]>::SampleCmpLevelZero(hlsl::SamplerComparisonState, float vector[2], float, int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerComparisonState") {{.*}}, <2 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(float2 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::Texture2D<float vector[4]>::SampleCmpLevelZero(hlsl::SamplerComparisonState, float vector[2], float, int vector[2])( +// CHECK-SAME: ptr noundef nonnull {{.*}} %[[THIS2:[^,]+]], ptr noundef byval(%"class.hlsl::SamplerComparisonState") {{.*}} %[[SAMPLER2:[^,]+]], <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <2 x float> %[[COORD_VAL2]], float %[[CMP_CAST2]], <2 x i32> %[[OFFSET_VAL2]]) diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-SampleGrad.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleGrad.hlsl new file mode 100644 index 0000000000000..279521c0bb988 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/Texture2D-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::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) } + +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") } + +Texture2D<float4> t; +SamplerState s; + +// CHECK-LABEL: @test_grad(float vector[2], float vector[2], float vector[2]) +// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[2], float vector[2], float vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 x float> {{.*}} %{{.*}}, <2 x float> {{.*}} %{{.*}}, <2 x float> {{.*}} %{{.*}}) +// CHECK: ret <4 x float> %[[CALL]] + +float4 test_grad(float2 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::Texture2D<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[2], float vector[2], float vector[2])( +// CHECK-SAME: ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <2 x float> {{.*}} %[[COORD:[^,]+]], <2 x float> {{.*}} %[[DDX:[^,]+]], <2 x float> {{.*}} %[[DDY:[^)]+]]) +// CHECK: %[[THIS_ADDR:.*]] = alloca ptr +// CHECK: %[[COORD_ADDR:.*]] = alloca <2 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 <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2f32.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <2 x float> %[[COORD_VAL]], <2 x float> %[[DDX_VAL]], <2 x float> %[[DDY_VAL]], <2 x i32> zeroinitializer) + +// CHECK-LABEL: @test_offset(float vector[2], float vector[2], float vector[2]) +// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[2], float vector[2], float vector[2], int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 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(float2 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::Texture2D<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[2], float vector[2], float vector[2], int vector[2])( +// CHECK-SAME: ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <2 x float> {{.*}} %[[COORD:[^,]+]], <2 x float> {{.*}} %[[DDX:[^,]+]], <2 x float> {{.*}} %[[DDY:[^,]+]], <2 x i32> {{.*}} %[[OFFSET:[^)]+]]) +// CHECK: %[[THIS_ADDR:.*]] = alloca ptr +// CHECK: %[[COORD_ADDR:.*]] = alloca <2 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 <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2f32.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <2 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[2], float vector[2], float vector[2]) +// CHECK: %[[CALL_CLAMP:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[2], float vector[2], float vector[2], int vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 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(float2 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::Texture2D<float vector[4]>::SampleGrad(hlsl::SamplerState, float vector[2], float vector[2], float vector[2], int vector[2], float)( +// CHECK-SAME: ptr {{.*}} %[[THIS:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER:[^,]+]], <2 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 <2 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 <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2f32.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE3]], target("dx.Sampler", 0) %[[SAMPLER_H3]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2f32.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE3]], target("spirv.Sampler") %[[SAMPLER_H3]], <2 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/Texture2D-SampleLevel.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleLevel.hlsl new file mode 100644 index 0000000000000..bcd025c164ac0 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/Texture2D-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::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) } + +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") } + +Texture2D<float4> t; +SamplerState s; + +// CHECK-LABEL: @test_level(float vector[2], float) +// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleLevel(hlsl::SamplerState, float vector[2], float)(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00) +// CHECK: ret <4 x float> %[[CALL]] + +float4 test_level(float2 loc : LOC, float lod : LOD) : SV_Target { + return t.SampleLevel(s, loc, 0.0f); +} + +// CHECK-LABEL: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleLevel(hlsl::SamplerState, float vector[2], float)( +// CHECK-SAME: ptr {{.*}} %[[THIS1:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER1:[^,]+]], <2 x float> noundef nofpclass(nan inf) %[[COORD1:[^,]+]], float noundef nofpclass(nan inf) %[[LOD1:[^)]+]]) +// CHECK: %[[THIS_ADDR1:.*]] = alloca ptr +// CHECK: %[[COORD_ADDR1:.*]] = alloca <2 x float> +// CHECK: %[[LOD_ADDR1:.*]] = alloca float +// CHECK: store ptr %[[THIS1]], ptr %[[THIS_ADDR1]] +// CHECK: store <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE1]], target("dx.Sampler", 0) %[[SAMPLER_H1]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE1]], target("spirv.Sampler") %[[SAMPLER_H1]], <2 x float> %[[COORD_VAL1]], float %[[LOD_CAST1]], <2 x i32> zeroinitializer) + +// CHECK-LABEL: @test_offset(float vector[2], float) +// CHECK: %[[CALL_OFFSET:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::SampleLevel(hlsl::SamplerState, float vector[2], float, int vector[2])(ptr {{.*}} @t, ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}}, <2 x float> {{.*}} %{{.*}}, float {{.*}} 0.000000e+00, <2 x i32> noundef <i32 1, i32 2>) +// CHECK: ret <4 x float> %[[CALL_OFFSET]] + +float4 test_offset(float2 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::Texture2D<float vector[4]>::SampleLevel(hlsl::SamplerState, float vector[2], float, int vector[2])( +// CHECK-SAME: ptr {{.*}} %[[THIS2:[^,]+]], ptr {{.*}} byval(%"class.hlsl::SamplerState") {{.*}} %[[SAMPLER2:[^,]+]], <2 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 <2 x float> +// CHECK: %[[LOD_ADDR2:.*]] = alloca float +// CHECK: %[[OFFSET_ADDR2:.*]] = alloca <2 x i32> +// CHECK: store ptr %[[THIS2]], ptr %[[THIS_ADDR2]] +// CHECK: store <2 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::Texture2D", 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 <2 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_2t.tdx.Sampler_0t.v2f32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE2]], target("dx.Sampler", 0) %[[SAMPLER_H2]], <2 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_0_0_1_0t.tspirv.Samplert.v2f32.v2i32(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE2]], target("spirv.Sampler") %[[SAMPLER_H2]], <2 x float> %[[COORD_VAL2]], float %[[LOD_CAST2]], <2 x i32> %[[OFFSET_VAL2]]) diff --git a/clang/test/SemaHLSL/Texture2D-SampleBias.hlsl b/clang/test/SemaHLSL/Texture2D-SampleBias.hlsl new file mode 100644 index 0000000000000..e49575c0dfc7d --- /dev/null +++ b/clang/test/SemaHLSL/Texture2D-SampleBias.hlsl @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s + +Texture2D<float4> tex; +SamplerState samp; + +void main() { + float2 loc = float2(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}} +} \ No newline at end of file diff --git a/clang/test/SemaHLSL/Texture2D-SampleCmp.hlsl b/clang/test/SemaHLSL/Texture2D-SampleCmp.hlsl new file mode 100644 index 0000000000000..b05fa2d59e29f --- /dev/null +++ b/clang/test/SemaHLSL/Texture2D-SampleCmp.hlsl @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -fsyntax-only -finclude-default-header -verify %s + + +Texture2D<float4> t; +Texture2D<int4> t_int; +SamplerComparisonState s; +SamplerState s2; + +void main(float2 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::Texture2D<vector<int, 4>>::SampleCmp' requested here}} + t_int.SampleCmp(s, loc, cmp); + + // expected-error@+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@+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@+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@+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@+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); +} \ No newline at end of file diff --git a/clang/test/SemaHLSL/Texture2D-SampleCmpLevelZero.hlsl b/clang/test/SemaHLSL/Texture2D-SampleCmpLevelZero.hlsl new file mode 100644 index 0000000000000..a0879e7bcae4a --- /dev/null +++ b/clang/test/SemaHLSL/Texture2D-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}} + +Texture2D<float4> t; +Texture2D<int4> t_int; +SamplerComparisonState s; +SamplerState s2; + +void main(float2 loc, float cmp) { + t.SampleCmpLevelZero(s, loc, cmp); + t.SampleCmpLevelZero(s, loc, cmp, int2(1, 2)); + + // expected-note@*:* {{in instantiation of member function 'hlsl::Texture2D<vector<int, 4>>::SampleCmpLevelZero' requested here}} + t_int.SampleCmpLevelZero(s, loc, cmp); + + // expected-error@+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@+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@+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@+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); +} \ No newline at end of file diff --git a/clang/test/SemaHLSL/Texture2D-SampleGrad.hlsl b/clang/test/SemaHLSL/Texture2D-SampleGrad.hlsl new file mode 100644 index 0000000000000..9705dc9e37d49 --- /dev/null +++ b/clang/test/SemaHLSL/Texture2D-SampleGrad.hlsl @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s + +Texture2D<float4> tex; +SamplerState samp; + +void main() { + float2 loc = float2(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/Texture2D-SampleLevel.hlsl b/clang/test/SemaHLSL/Texture2D-SampleLevel.hlsl new file mode 100644 index 0000000000000..43f3815201b10 --- /dev/null +++ b/clang/test/SemaHLSL/Texture2D-SampleLevel.hlsl @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s + +Texture2D<float4> tex; +SamplerState samp; + +void main() { + float2 loc = float2(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}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
