diff --git a/include/dxc/dxcapi.internal.h b/include/dxc/dxcapi.internal.h index e2ab229b2f..7a83dd6d01 100644 --- a/include/dxc/dxcapi.internal.h +++ b/include/dxc/dxcapi.internal.h @@ -140,7 +140,8 @@ enum LEGAL_INTRINSIC_COMPTYPES { #ifdef ENABLE_SPIRV_CODEGEN LICOMPTYPE_VK_BUFFER_POINTER = 56, - LICOMPTYPE_COUNT = 57 + LICOMPTYPE_VK_SAMPLED_TEXTURE2D = 57, + LICOMPTYPE_COUNT = 58 #else LICOMPTYPE_COUNT = 56 #endif diff --git a/tools/clang/include/clang/AST/HlslTypes.h b/tools/clang/include/clang/AST/HlslTypes.h index 43c1effdb8..610d844616 100644 --- a/tools/clang/include/clang/AST/HlslTypes.h +++ b/tools/clang/include/clang/AST/HlslTypes.h @@ -407,6 +407,10 @@ clang::CXXRecordDecl * DeclareVkBufferPointerType(clang::ASTContext &context, clang::DeclContext *declContext); +clang::CXXRecordDecl *DeclareVkSampledTextureType( + clang::ASTContext &context, clang::DeclContext *declContext, + llvm::StringRef hlslTypeName, clang::QualType defaultParamType); + clang::CXXRecordDecl *DeclareInlineSpirvType(clang::ASTContext &context, clang::DeclContext *declContext, llvm::StringRef typeName, diff --git a/tools/clang/include/clang/SPIRV/AstTypeProbe.h b/tools/clang/include/clang/SPIRV/AstTypeProbe.h index 45bff1bad4..1479075f12 100644 --- a/tools/clang/include/clang/SPIRV/AstTypeProbe.h +++ b/tools/clang/include/clang/SPIRV/AstTypeProbe.h @@ -257,6 +257,9 @@ bool isTexture(QualType); /// Texture2DMSArray type. bool isTextureMS(QualType); +/// \brief Returns true if the given type is an HLSL SampledTexture type. +bool isSampledTexture(QualType); + /// \brief Returns true if the given type is an HLSL RWTexture type. bool isRWTexture(QualType); diff --git a/tools/clang/include/clang/SPIRV/SpirvBuilder.h b/tools/clang/include/clang/SPIRV/SpirvBuilder.h index 122f461a5f..868c978c35 100644 --- a/tools/clang/include/clang/SPIRV/SpirvBuilder.h +++ b/tools/clang/include/clang/SPIRV/SpirvBuilder.h @@ -287,6 +287,10 @@ class SpirvBuilder { /// If compareVal is given a non-zero value, *Dref* variants of OpImageSample* /// will be generated. /// + /// If sampler is set, it defines the sampler along *image* to create the + /// combined image sampler. Otherwise, the *image* parameter must point to a + /// sampled image. + /// /// If lod or grad is given a non-zero value, *ExplicitLod variants of /// OpImageSample* will be generated; otherwise, *ImplicitLod variant will /// be generated. diff --git a/tools/clang/lib/AST/ASTContextHLSL.cpp b/tools/clang/lib/AST/ASTContextHLSL.cpp index a524dfab7f..1482d09a3f 100644 --- a/tools/clang/lib/AST/ASTContextHLSL.cpp +++ b/tools/clang/lib/AST/ASTContextHLSL.cpp @@ -1372,6 +1372,26 @@ CXXRecordDecl *hlsl::DeclareNodeOrRecordType( } #ifdef ENABLE_SPIRV_CODEGEN +CXXRecordDecl *hlsl::DeclareVkSampledTextureType(ASTContext &context, + DeclContext *declContext, + llvm::StringRef hlslTypeName, + QualType defaultParamType) { + // TODO(https://github.com/microsoft/DirectXShaderCompiler/issues/7979): Later + // generalize these to all SampledTexture types. + BuiltinTypeDeclBuilder Builder(declContext, hlslTypeName, + TagDecl::TagKind::TTK_Struct); + + TemplateTypeParmDecl *TyParamDecl = + Builder.addTypeTemplateParam("SampledTextureType", defaultParamType); + + Builder.startDefinition(); + + QualType paramType = QualType(TyParamDecl->getTypeForDecl(), 0); + CXXRecordDecl *recordDecl = Builder.getRecordDecl(); + + return recordDecl; +} + CXXRecordDecl *hlsl::DeclareVkBufferPointerType(ASTContext &context, DeclContext *declContext) { BuiltinTypeDeclBuilder Builder(declContext, "BufferPointer", diff --git a/tools/clang/lib/SPIRV/AstTypeProbe.cpp b/tools/clang/lib/SPIRV/AstTypeProbe.cpp index fda9a3ab3e..48c3012501 100644 --- a/tools/clang/lib/SPIRV/AstTypeProbe.cpp +++ b/tools/clang/lib/SPIRV/AstTypeProbe.cpp @@ -926,6 +926,17 @@ bool isTexture(QualType type) { return false; } +bool isSampledTexture(QualType type) { + if (const auto *rt = type->getAs()) { + const auto name = rt->getDecl()->getName(); + // TODO(https://github.com/microsoft/DirectXShaderCompiler/issues/7979): Add + // other sampled texture types as needed. + if (name == "SampledTexture2D") + return true; + } + return false; +} + bool isTextureMS(QualType type) { if (const auto *rt = type->getAs()) { const auto name = rt->getDecl()->getName(); diff --git a/tools/clang/lib/SPIRV/LowerTypeVisitor.cpp b/tools/clang/lib/SPIRV/LowerTypeVisitor.cpp index b660ea70df..38d2adf166 100644 --- a/tools/clang/lib/SPIRV/LowerTypeVisitor.cpp +++ b/tools/clang/lib/SPIRV/LowerTypeVisitor.cpp @@ -849,6 +849,23 @@ const SpirvType *LowerTypeVisitor::lowerVkTypeInVkNamespace( assert(visitedTypeStack.size() == visitedTypeStackSize); return pointerType; } + if (name == "SampledTexture2D") { + const auto sampledType = hlsl::GetHLSLResourceResultType(type); + auto loweredType = lowerType(getElementType(astContext, sampledType), rule, + /*isRowMajor*/ llvm::None, srcLoc); + + // Bool does not have a defined size in SPIR-V, so it cannot be + // used in the external interface. + if (loweredType == spvContext.getBoolType()) { + loweredType = spvContext.getUIntType(32); + } + + const auto *imageType = spvContext.getImageType( + loweredType, spv::Dim::Dim2D, ImageType::WithDepth::No, + false /* array */, false /* ms */, ImageType::WithSampler::Yes, + spv::ImageFormat::Unknown); + return spvContext.getSampledImageType(imageType); + } emitError("unknown type %0 in vk namespace", srcLoc) << type; return nullptr; } @@ -892,7 +909,8 @@ LowerTypeVisitor::lowerResourceType(QualType type, SpirvLayoutRule rule, auto loweredType = lowerType(getElementType(astContext, sampledType), rule, /*isRowMajor*/ llvm::None, srcLoc); - // Treat bool textures as uint for compatibility with OpTypeImage. + // Bool does not have a defined size in SPIR-V, so it cannot be + // used in the external interface. if (loweredType == spvContext.getBoolType()) { loweredType = spvContext.getUIntType(32); } diff --git a/tools/clang/lib/SPIRV/SpirvBuilder.cpp b/tools/clang/lib/SPIRV/SpirvBuilder.cpp index 5169ee7b13..7ce0508585 100644 --- a/tools/clang/lib/SPIRV/SpirvBuilder.cpp +++ b/tools/clang/lib/SPIRV/SpirvBuilder.cpp @@ -620,8 +620,15 @@ SpirvInstruction *SpirvBuilder::createImageSample( assert(lod == nullptr || minLod == nullptr); // An OpSampledImage is required to do the image sampling. - auto *sampledImage = - createSampledImage(imageType, image, sampler, loc, range); + // Skip creating OpSampledImage if the imageType is a sampled texture. + SpirvInstruction *sampledImage; + if (isSampledTexture(imageType)) { + assert(!sampler && + "sampler must be null when sampling from a sampled texture"); + sampledImage = image; + } else { + sampledImage = createSampledImage(imageType, image, sampler, loc, range); + } const auto mask = composeImageOperandsMask( bias, lod, grad, constOffset, varOffset, constOffsets, sample, minLod); diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index c41e300975..f77e9ac82b 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -4474,14 +4474,27 @@ SpirvEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr, // TextureCube(Array).CalculateLevelOfDetail(SamplerState S, float3 xyz); // Texture3D.CalculateLevelOfDetail(SamplerState S, float3 xyz); // Return type is always a single float (LOD). - assert(expr->getNumArgs() == 2u); - const auto *object = expr->getImplicitObjectArgument(); - auto *objectInfo = loadIfGLValue(object); - auto *samplerState = doExpr(expr->getArg(0)); - auto *coordinate = doExpr(expr->getArg(1)); + // + // Their SampledTexture variants have the same signature without the + // sampler_state parameter. + const auto *imageExpr = expr->getImplicitObjectArgument(); + const QualType imageType = imageExpr->getType(); + // numarg is 1 if isSampledTexture(imageType). otherwise 2. + assert(expr->getNumArgs() == (isSampledTexture(imageType) ? 1u : 2u)); + + auto *objectInfo = loadIfGLValue(imageExpr); - auto *sampledImage = spvBuilder.createSampledImage( - object->getType(), objectInfo, samplerState, expr->getExprLoc()); + SpirvInstruction *samplerState, *coordinate, *sampledImage; + if (isSampledTexture(imageType)) { + samplerState = nullptr; + coordinate = doExpr(expr->getArg(0)); + sampledImage = objectInfo; + } else { + samplerState = doExpr(expr->getArg(0)); + coordinate = doExpr(expr->getArg(1)); + sampledImage = spvBuilder.createSampledImage( + imageExpr->getType(), objectInfo, samplerState, expr->getExprLoc()); + } // The result type of OpImageQueryLod must be a float2. const QualType queryResultType = @@ -5817,6 +5830,9 @@ SpirvEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr, // [, float Clamp] // [, out uint Status]); // + // Their SampledTexture variants have the same signature without the + // sampler_state parameter. + // // For TextureCube and TextureCubeArray: // DXGI_FORMAT Object.Sample(sampler_state S, // float Location @@ -5835,35 +5851,49 @@ SpirvEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr, // [, uint Status]); // // Other Texture types do not have a Gather method. - const auto numArgs = expr->getNumArgs(); const auto loc = expr->getExprLoc(); const auto range = expr->getSourceRange(); const bool hasStatusArg = expr->getArg(numArgs - 1)->getType()->isUnsignedIntegerType(); + const auto *imageExpr = expr->getImplicitObjectArgument(); + const QualType imageType = imageExpr->getType(); + const bool isImageSampledTexture = isSampledTexture(imageType); + + int samplerIndex; + uint32_t coordIndex; + if (isImageSampledTexture) { + samplerIndex = -1; // non-existant + coordIndex = 0; + } else { + samplerIndex = 0; + coordIndex = 1; + } + SpirvInstruction *clamp = nullptr; - if (numArgs > 2 && expr->getArg(2)->getType()->isFloatingType()) - clamp = doExpr(expr->getArg(2)); - else if (numArgs > 3 && expr->getArg(3)->getType()->isFloatingType()) - clamp = doExpr(expr->getArg(3)); + if (numArgs > coordIndex + 1 && + expr->getArg(coordIndex + 1)->getType()->isFloatingType()) + clamp = doExpr(expr->getArg(coordIndex + 1)); + else if (numArgs > coordIndex + 2 && + expr->getArg(coordIndex + 2)->getType()->isFloatingType()) + clamp = doExpr(expr->getArg(coordIndex + 2)); const bool hasClampArg = (clamp != 0); const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : nullptr; - // Subtract 1 for status (if it exists), subtract 1 for clamp (if it exists), - // and subtract 2 for sampler_state and location. - const bool hasOffsetArg = numArgs - hasStatusArg - hasClampArg - 2 > 0; - - const auto *imageExpr = expr->getImplicitObjectArgument(); - const QualType imageType = imageExpr->getType(); auto *image = loadIfGLValue(imageExpr); - auto *sampler = doExpr(expr->getArg(0)); - auto *coordinate = doExpr(expr->getArg(1)); + SpirvInstruction *sampler = + samplerIndex >= 0 ? doExpr(expr->getArg(samplerIndex)) : nullptr; + auto *coordinate = doExpr(expr->getArg(coordIndex)); // .Sample()/.Gather() may have a third optional paramter for offset. SpirvInstruction *constOffset = nullptr, *varOffset = nullptr; + // Subtract 1 for status (if it exists), subtract 1 for clamp (if it exists), + // and subtract offsetIndex for sampler_state (if exists) location. + const bool hasOffsetArg = + numArgs - hasStatusArg - hasClampArg - coordIndex > 1; if (hasOffsetArg) - handleOffsetInMethodCall(expr, 2, &constOffset, &varOffset); + handleOffsetInMethodCall(expr, coordIndex + 1, &constOffset, &varOffset); const auto retType = expr->getDirectCallee()->getReturnType(); if (isSample) { diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 925a9e5abf..d41816a8a2 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -199,6 +199,7 @@ enum ArBasicKind { AR_OBJECT_VK_SPV_INTRINSIC_TYPE, AR_OBJECT_VK_SPV_INTRINSIC_RESULT_ID, AR_OBJECT_VK_BUFFER_POINTER, + AR_OBJECT_VK_SAMPLED_TEXTURE2D, #endif // ENABLE_SPIRV_CODEGEN // SPIRV change ends @@ -559,6 +560,7 @@ const UINT g_uBasicKindProps[] = { BPROP_OBJECT, // AR_OBJECT_VK_SPV_INTRINSIC_TYPE use recordType BPROP_OBJECT, // AR_OBJECT_VK_SPV_INTRINSIC_RESULT_ID use recordType BPROP_OBJECT, // AR_OBJECT_VK_BUFFER_POINTER use recordType + BPROP_OBJECT | BPROP_RBUFFER, // AR_OBJECT_VK_SAMPLED_TEXTURE2D #endif // ENABLE_SPIRV_CODEGEN // SPIRV change ends @@ -1267,6 +1269,8 @@ static const ArBasicKind g_LinAlgMatrixCT[] = {AR_OBJECT_LINALG_MATRIX, #ifdef ENABLE_SPIRV_CODEGEN static const ArBasicKind g_VKBufferPointerCT[] = {AR_OBJECT_VK_BUFFER_POINTER, AR_BASIC_UNKNOWN}; +static const ArBasicKind g_VKSampledTexture2DCT[] = { + AR_OBJECT_VK_SAMPLED_TEXTURE2D, AR_BASIC_UNKNOWN}; #endif // Basic kinds, indexed by a LEGAL_INTRINSIC_COMPTYPES value. @@ -1329,7 +1333,8 @@ const ArBasicKind *g_LegalIntrinsicCompTypes[] = { g_LinAlgCT, // LICOMPTYPE_LINALG g_BuiltInTrianglePositionsCT, // LICOMPTYPE_BUILTIN_TRIANGLE_POSITIONS #ifdef ENABLE_SPIRV_CODEGEN - g_VKBufferPointerCT, // LICOMPTYPE_VK_BUFFER_POINTER + g_VKBufferPointerCT, // LICOMPTYPE_VK_BUFFER_POINTER + g_VKSampledTexture2DCT, // LICOMPTYPE_VK_SAMPLED_TEXTURE2D #endif }; static_assert( @@ -1389,7 +1394,7 @@ static const ArBasicKind g_ArBasicKindsAsTypes[] = { AR_OBJECT_VK_SPIRV_TYPE, AR_OBJECT_VK_SPIRV_OPAQUE_TYPE, AR_OBJECT_VK_INTEGRAL_CONSTANT, AR_OBJECT_VK_LITERAL, AR_OBJECT_VK_SPV_INTRINSIC_TYPE, AR_OBJECT_VK_SPV_INTRINSIC_RESULT_ID, - AR_OBJECT_VK_BUFFER_POINTER, + AR_OBJECT_VK_BUFFER_POINTER, AR_OBJECT_VK_SAMPLED_TEXTURE2D, #endif // ENABLE_SPIRV_CODEGEN // SPIRV change ends @@ -1501,6 +1506,7 @@ static const uint8_t g_ArBasicKindsTemplateCount[] = { 1, // AR_OBJECT_VK_SPV_INTRINSIC_TYPE 1, // AR_OBJECT_VK_SPV_INTRINSIC_RESULT_ID 2, // AR_OBJECT_VK_BUFFER_POINTER + 1, // AR_OBJECT_VK_SAMPLED_TEXTURE2D #endif // ENABLE_SPIRV_CODEGEN // SPIRV change ends @@ -1654,6 +1660,7 @@ static const SubscriptOperatorRecord g_ArBasicKindsSubscripts[] = { {0, MipsFalse, SampleFalse}, // AR_OBJECT_VK_SPV_INTRINSIC_TYPE {0, MipsFalse, SampleFalse}, // AR_OBJECT_VK_SPV_INTRINSIC_RESULT_ID {0, MipsFalse, SampleFalse}, // AR_OBJECT_VK_BUFFER_POINTER + {0, MipsFalse, SampleFalse}, // AR_OBJECT_VK_SAMPLED_TEXTURE2D #endif // ENABLE_SPIRV_CODEGEN // SPIRV change ends @@ -1823,6 +1830,7 @@ static const char *g_ArBasicTypeNames[] = { "ext_type", "ext_result_id", "BufferPointer", + "SampledTexture2D", #endif // ENABLE_SPIRV_CODEGEN // SPIRV change ends @@ -2475,6 +2483,12 @@ static void GetIntrinsicMethods(ArBasicKind kind, *intrinsics = g_RayQueryMethods; *intrinsicCount = _countof(g_RayQueryMethods); break; +#ifdef ENABLE_SPIRV_CODEGEN + case AR_OBJECT_VK_SAMPLED_TEXTURE2D: + *intrinsics = g_VkSampledTexture2DMethods; + *intrinsicCount = _countof(g_VkSampledTexture2DMethods); + break; +#endif case AR_OBJECT_HIT_OBJECT: *intrinsics = g_DxHitObjectMethods; *intrinsicCount = _countof(g_DxHitObjectMethods); @@ -3073,6 +3087,7 @@ class HLSLExternalSource : public ExternalSemaSource { ClassTemplateDecl *m_vkIntegralConstantTemplateDecl; ClassTemplateDecl *m_vkLiteralTemplateDecl; ClassTemplateDecl *m_vkBufferPointerTemplateDecl; + ClassTemplateDecl *m_vkSampledTextureTemplateDecl; // Declarations for Work Graph Output Record types ClassTemplateDecl *m_GroupNodeOutputRecordsTemplateDecl; @@ -4078,6 +4093,15 @@ class HLSLExternalSource : public ExternalSemaSource { recordDecl = DeclareVkBufferPointerType(*m_context, m_vkNSDecl); recordDecl->setImplicit(true); m_vkBufferPointerTemplateDecl = recordDecl->getDescribedClassTemplate(); + } else if (kind == AR_OBJECT_VK_SAMPLED_TEXTURE2D) { + if (!m_vkNSDecl) + continue; + QualType float4Type = + LookupVectorType(HLSLScalarType::HLSLScalarType_float, 4); + recordDecl = DeclareVkSampledTextureType( + *m_context, m_vkNSDecl, "SampledTexture2D", float4Type); + m_vkSampledTextureTemplateDecl = + recordDecl->getDescribedClassTemplate(); } #endif else if (templateArgCount == 0) { @@ -4191,7 +4215,8 @@ class HLSLExternalSource : public ExternalSemaSource { : m_matrixTemplateDecl(nullptr), m_vectorTemplateDecl(nullptr), m_vkIntegralConstantTemplateDecl(nullptr), m_vkLiteralTemplateDecl(nullptr), - m_vkBufferPointerTemplateDecl(nullptr), m_hlslNSDecl(nullptr), + m_vkBufferPointerTemplateDecl(nullptr), + m_vkSampledTextureTemplateDecl(nullptr), m_hlslNSDecl(nullptr), m_vkNSDecl(nullptr), m_dxNSDecl(nullptr), m_context(nullptr), m_sema(nullptr), m_hlslStringTypedef(nullptr) { memset(m_matrixTypes, 0, sizeof(m_matrixTypes)); diff --git a/tools/clang/test/CodeGenSPIRV/vk.sampledtexture.calculate-lod.hlsl b/tools/clang/test/CodeGenSPIRV/vk.sampledtexture.calculate-lod.hlsl new file mode 100644 index 0000000000..01d3efb5aa --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/vk.sampledtexture.calculate-lod.hlsl @@ -0,0 +1,21 @@ +// RUN: %dxc -T ps_6_0 -E main -fcgl %s -spirv | FileCheck %s + +// CHECK: OpCapability ImageQuery + +vk::SampledTexture2D t1 : register(t0); + +// CHECK: %type_2d_image = OpTypeImage %float 2D 0 0 0 1 Unknown +// CHECK: %type_sampled_image = OpTypeSampledImage %type_2d_image +// CHECK: [[ptr:%[a-zA-Z0-9_]+]] = OpTypePointer UniformConstant %type_sampled_image + +// CHECK: %t1 = OpVariable [[ptr]] UniformConstant + +void main() { + float2 xy = float2(0.5, 0.5); + +//CHECK: [[tex1:%[a-zA-Z0-9_]+]] = OpLoad %type_sampled_image %t1 +//CHECK-NEXT: [[xy_load:%[a-zA-Z0-9_]+]] = OpLoad %v2float %xy +//CHECK-NEXT: [[query:%[a-zA-Z0-9_]+]] = OpImageQueryLod %v2float [[tex1]] [[xy_load]] +//CHECK-NEXT: {{%[0-9]+}} = OpCompositeExtract %float [[query]] 0 + float lod = t1.CalculateLevelOfDetail(xy); +} diff --git a/tools/clang/test/CodeGenSPIRV/vk.sampledtexture.sample.hlsl b/tools/clang/test/CodeGenSPIRV/vk.sampledtexture.sample.hlsl new file mode 100644 index 0000000000..ee4051f45c --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/vk.sampledtexture.sample.hlsl @@ -0,0 +1,50 @@ +// RUN: %dxc -T ps_6_7 -E main -fcgl %s -spirv | FileCheck %s + +// CHECK: OpCapability MinLod +// CHECK: OpCapability SparseResidency + +// CHECK: [[v2fc:%[0-9]+]] = OpConstantComposite %v2float %float_0_5 %float_0_25 +// CHECK: [[v2ic:%[0-9]+]] = OpConstantComposite %v2int %int_2 %int_3 + +// CHECK: [[type_2d_image_1:%[a-zA-Z0-9_]+]] = OpTypeImage %float 2D 0 0 0 1 Unknown +// CHECK: [[type_sampled_image_1:%[a-zA-Z0-9_]+]] = OpTypeSampledImage [[type_2d_image_1]] +// CHECK: [[ptr_type_1:%[a-zA-Z0-9_]+]] = OpTypePointer UniformConstant [[type_sampled_image_1]] + +// CHECK: [[type_2d_image_2:%[a-zA-Z0-9_]+]] = OpTypeImage %uint 2D 0 0 0 1 Unknown +// CHECK: [[type_sampled_image_2:%[a-zA-Z0-9_]+]] = OpTypeSampledImage [[type_2d_image_2]] +// CHECK: [[ptr_type_2:%[a-zA-Z0-9_]+]] = OpTypePointer UniformConstant [[type_sampled_image_2]] + +// CHECK: [[tex1:%[a-zA-Z0-9_]+]] = OpVariable [[ptr_type_1]] UniformConstant +// CHECK: [[tex2:%[a-zA-Z0-9_]+]] = OpVariable [[ptr_type_1]] UniformConstant +// CHECK: [[tex3:%[a-zA-Z0-9_]+]] = OpVariable [[ptr_type_2]] UniformConstant + +vk::SampledTexture2D tex1 : register(t0); +vk::SampledTexture2D tex2 : register(t1); +vk::SampledTexture2D tex3 : register(t2); + +float4 main() : SV_Target { +// CHECK: [[tex1_load:%[a-zA-Z0-9_]+]] = OpLoad [[type_sampled_image_1]] [[tex1]] +// CHECK: [[sampled_result1:%[a-zA-Z0-9_]+]] = OpImageSampleImplicitLod %v4float [[tex1_load]] [[v2fc]] None + float4 val1 = tex1.Sample(float2(0.5, 0.25)); + +// CHECK: [[tex2_load:%[a-zA-Z0-9_]+]] = OpLoad [[type_sampled_image_1]] [[tex2]] +// CHECK: [[sampled_result2:%[a-zA-Z0-9_]+]] = OpImageSampleImplicitLod %v4float [[tex2_load]] [[v2fc]] ConstOffset [[v2ic]] + float4 val2 = tex2.Sample(float2(0.5, 0.25), int2(2, 3)); + +// CHECK: [[tex3_load:%[a-zA-Z0-9_]+]] = OpLoad [[type_sampled_image_1]] [[tex2]] +// CHECK: [[sampled_result3:%[a-zA-Z0-9_]+]] = OpImageSampleImplicitLod %v4float [[tex3_load]] [[v2fc]] ConstOffset|MinLod [[v2ic]] %float_1 + float4 val3 = tex2.Sample(float2(0.5, 0.25), int2(2, 3), 1.0f); + +// CHECK: [[tex4_load:%[a-zA-Z0-9_]+]] = OpLoad [[type_sampled_image_1]] [[tex2]] +// CHECK: [[sampled_result4:%[a-zA-Z0-9_]+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct [[tex4_load]] [[v2fc]] ConstOffset|MinLod [[v2ic]] %float_1 +// CHECK: [[status_0:%[a-zA-Z0-9_]+]] = OpCompositeExtract %uint [[sampled_result4]] 0 +// CHECK: OpStore %status [[status_0]] + uint status; + float4 val4 = tex2.Sample(float2(0.5, 0.25), int2(2, 3), 1.0f, status); + +// CHECK: [[tex5_load:%[a-zA-Z0-9_]+]] = OpLoad [[type_sampled_image_2]] [[tex3]] +// CHECK: [[sampled_result5:%[a-zA-Z0-9_]+]] = OpImageSampleImplicitLod %v4uint [[tex5_load]] [[v2fc]] None +// CHECK: [[val5:%[a-zA-Z0-9_]+]] = OpCompositeExtract %uint [[sampled_result5]] 0 + uint val5 = tex3.Sample(float2(0.5, 0.25)); + return 1.0; +} diff --git a/tools/clang/test/SemaHLSL/vk.sampledtexture.struct.error.hlsl b/tools/clang/test/SemaHLSL/vk.sampledtexture.struct.error.hlsl new file mode 100644 index 0000000000..6f1db1f871 --- /dev/null +++ b/tools/clang/test/SemaHLSL/vk.sampledtexture.struct.error.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T ps_6_0 -E main %s -spirv -fcgl -verify + +struct Struct { float f; }; + +vk::SampledTexture2D t; + +float4 main(float2 f2 : F2) : SV_TARGET +{ + return t.Sample(f2); // expected-error {{cannot Sample from resource containing}} expected-error {{cannot initialize return object}} +} diff --git a/utils/hct/gen_intrin_main.txt b/utils/hct/gen_intrin_main.txt index 5f61b5b6ab..f799ee2810 100644 --- a/utils/hct/gen_intrin_main.txt +++ b/utils/hct/gen_intrin_main.txt @@ -1234,3 +1234,11 @@ $classT [[]] SubpassLoad(in int sample) : subpassinputms_load; } namespace // SPIRV Change Ends + +namespace VkSampledTexture2DMethods { + $classT [[ro]] Sample(in float<2> x) : tex2d_t; + $classT [[ro]] Sample(in float<2> x, in int<2> o) : tex2d_t_o; + $classT [[ro]] Sample(in float<2> x, in int<2> o, in float clamp) : tex2d_t_o_cl; + $classT [[]] Sample(in float<2> x, in int<2> o, in float clamp, out uint_only status) : tex2d_t_o_cl_s; + float [[ro]] CalculateLevelOfDetail(in float<2> x) : tex2d_t_calc_lod; +} namespace diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index 69fd14be6b..09a688fd39 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -9696,7 +9696,7 @@ def load_intrinsics(self, intrinsic_defs): acceleration_struct | ray_desc | RayQuery | DxHitObject | Node\w* | RWNode\w* | EmptyNode\w* | AnyNodeOutput\w* | NodeOutputRecord\w* | GroupShared\w* | - VkBufferPointer | LinAlgMatrix + VkBufferPointer | LinAlgMatrix | VkSampledTexture2D $)""", flags=re.VERBOSE, )