-
Notifications
You must be signed in to change notification settings - Fork 828
[SPIR-V] Add vk::SampledTexture2D resource type and .Sample(), .CalculateLevelOfDetail() method.
#8047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[SPIR-V] Add vk::SampledTexture2D resource type and .Sample(), .CalculateLevelOfDetail() method.
#8047
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1369,6 +1369,86 @@ CXXRecordDecl *hlsl::DeclareNodeOrRecordType( | |
| } | ||
|
|
||
| #ifdef ENABLE_SPIRV_CODEGEN | ||
| CXXRecordDecl *hlsl::DeclareVkSampledTexture2DType(ASTContext &context, | ||
| DeclContext *declContext, | ||
| QualType float2Type, | ||
| QualType int2Type, | ||
| QualType float4Type) { | ||
|
||
| BuiltinTypeDeclBuilder Builder(declContext, "SampledTexture2D", | ||
| TagDecl::TagKind::TTK_Struct); | ||
|
|
||
| QualType defaultTextureType = float4Type; | ||
| TemplateTypeParmDecl *TyParamDecl = | ||
| Builder.addTypeTemplateParam("SampledTextureType", defaultTextureType); | ||
|
|
||
| Builder.startDefinition(); | ||
|
|
||
| QualType paramType = QualType(TyParamDecl->getTypeForDecl(), 0); | ||
| CXXRecordDecl *recordDecl = Builder.getRecordDecl(); | ||
|
|
||
| QualType floatType = context.FloatTy; | ||
| QualType uintType = context.UnsignedIntTy; | ||
| // Add Sample method | ||
| // Sample(location) | ||
| CXXMethodDecl *sampleDecl = CreateObjectFunctionDeclarationWithParams( | ||
| context, recordDecl, paramType, ArrayRef<QualType>(float2Type), | ||
| ArrayRef<StringRef>(StringRef("location")), | ||
| context.DeclarationNames.getIdentifier(&context.Idents.get("Sample")), | ||
| /*isConst*/ true); | ||
| sampleDecl->addAttr(HLSLIntrinsicAttr::CreateImplicit( | ||
| context, "op", "", static_cast<int>(hlsl::IntrinsicOp::MOP_Sample))); | ||
| sampleDecl->addAttr(HLSLCXXOverloadAttr::CreateImplicit(context)); | ||
|
|
||
| // Sample(location, offset) | ||
| QualType params2[] = {float2Type, int2Type}; | ||
| StringRef names2[] = {"location", "offset"}; | ||
| CXXMethodDecl *sampleDecl2 = CreateObjectFunctionDeclarationWithParams( | ||
| context, recordDecl, paramType, params2, names2, | ||
| context.DeclarationNames.getIdentifier(&context.Idents.get("Sample")), | ||
| /*isConst*/ true); | ||
| sampleDecl2->addAttr(HLSLIntrinsicAttr::CreateImplicit( | ||
| context, "op", "", static_cast<int>(hlsl::IntrinsicOp::MOP_Sample))); | ||
| sampleDecl2->addAttr(HLSLCXXOverloadAttr::CreateImplicit(context)); | ||
|
|
||
| // Sample(location, offset, clamp) | ||
| QualType params3[] = {float2Type, int2Type, floatType}; | ||
| StringRef names3[] = {"location", "offset", "clamp"}; | ||
| CXXMethodDecl *sampleDecl3 = CreateObjectFunctionDeclarationWithParams( | ||
| context, recordDecl, paramType, params3, names3, | ||
| context.DeclarationNames.getIdentifier(&context.Idents.get("Sample")), | ||
| /*isConst*/ true); | ||
| sampleDecl3->addAttr(HLSLIntrinsicAttr::CreateImplicit( | ||
| context, "op", "", static_cast<int>(hlsl::IntrinsicOp::MOP_Sample))); | ||
| sampleDecl3->addAttr(HLSLCXXOverloadAttr::CreateImplicit(context)); | ||
|
|
||
| // Sample(location, offset, clamp, status) | ||
| QualType params4[] = {float2Type, int2Type, floatType, | ||
| context.getLValueReferenceType(uintType)}; | ||
| StringRef names4[] = {"location", "offset", "clamp", "status"}; | ||
| CXXMethodDecl *sampleDecl4 = CreateObjectFunctionDeclarationWithParams( | ||
| context, recordDecl, paramType, params4, names4, | ||
|
||
| context.DeclarationNames.getIdentifier(&context.Idents.get("Sample")), | ||
| /*isConst*/ true); | ||
| sampleDecl4->addAttr(HLSLIntrinsicAttr::CreateImplicit( | ||
| context, "op", "", static_cast<int>(hlsl::IntrinsicOp::MOP_Sample))); | ||
| sampleDecl4->addAttr(HLSLCXXOverloadAttr::CreateImplicit(context)); | ||
|
|
||
| // CalculateLevelOfDetail(location) | ||
| CXXMethodDecl *lodDecl = CreateObjectFunctionDeclarationWithParams( | ||
| context, recordDecl, floatType, ArrayRef<QualType>(float2Type), | ||
| ArrayRef<StringRef>(StringRef("location")), | ||
| context.DeclarationNames.getIdentifier( | ||
| &context.Idents.get("CalculateLevelOfDetail")), | ||
| /*isConst*/ true); | ||
| lodDecl->addAttr(HLSLIntrinsicAttr::CreateImplicit( | ||
| context, "op", "", | ||
| static_cast<int>(hlsl::IntrinsicOp::MOP_CalculateLevelOfDetail))); | ||
| lodDecl->addAttr(HLSLCXXOverloadAttr::CreateImplicit(context)); | ||
|
|
||
| Builder.completeDefinition(); | ||
| return recordDecl; | ||
| } | ||
|
|
||
| CXXRecordDecl *hlsl::DeclareVkBufferPointerType(ASTContext &context, | ||
| DeclContext *declContext) { | ||
| BuiltinTypeDeclBuilder Builder(declContext, "BufferPointer", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -849,6 +849,22 @@ 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); | ||
|
|
||
| // Treat bool textures as uint for compatibility with OpTypeImage. | ||
|
||
| 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; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4451,15 +4451,25 @@ SpirvEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr, | |
| // Texture2D(Array).CalculateLevelOfDetail(SamplerState S, float2 xy); | ||
| // TextureCube(Array).CalculateLevelOfDetail(SamplerState S, float3 xyz); | ||
| // Texture3D.CalculateLevelOfDetail(SamplerState S, float3 xyz); | ||
| // SampledTexture2D.CalculateLevelOfDetail(float2 xy); | ||
| // 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)); | ||
|
|
||
| auto *sampledImage = spvBuilder.createSampledImage( | ||
| object->getType(), objectInfo, samplerState, expr->getExprLoc()); | ||
| 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 *samplerState = | ||
| isSampledTexture(imageType) ? nullptr : doExpr(expr->getArg(0)); | ||
| auto *coordinate = isSampledTexture(imageType) ? doExpr(expr->getArg(0)) | ||
| : doExpr(expr->getArg(1)); | ||
|
|
||
| auto *sampledImage = | ||
| isSampledTexture(imageType) | ||
luciechoi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ? objectInfo | ||
| : spvBuilder.createSampledImage(imageExpr->getType(), objectInfo, | ||
| samplerState, expr->getExprLoc()); | ||
|
|
||
| // The result type of OpImageQueryLod must be a float2. | ||
| const QualType queryResultType = | ||
|
|
@@ -5812,11 +5822,54 @@ SpirvEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr, | |
| // float2|3|4 Location | ||
| // [, uint Status]); | ||
| // | ||
| // For SampledTexture2D: | ||
| // DXGI_FORMAT Object.Sample(float Location | ||
| // [, int Offset] | ||
| // [, float Clamp] | ||
| // [, out 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 auto *imageExpr = expr->getImplicitObjectArgument(); | ||
| const QualType imageType = imageExpr->getType(); | ||
|
|
||
| if (isSampledTexture(imageType)) { | ||
| auto *sampledImage = loadIfGLValue(imageExpr); | ||
| auto *coordinate = doExpr(expr->getArg(0)); | ||
| SpirvInstruction *constOffset = nullptr; | ||
| SpirvInstruction *varOffset = nullptr; | ||
| SpirvInstruction *clamp = nullptr; | ||
| SpirvInstruction *status = nullptr; | ||
|
|
||
| if (numArgs > 1) { | ||
| handleOffsetInMethodCall(expr, 1, &constOffset, &varOffset); | ||
| } | ||
| if (numArgs > 2) { | ||
luciechoi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| clamp = doExpr(expr->getArg(2)); | ||
| } | ||
| if (numArgs > 3) { | ||
| status = doExpr(expr->getArg(3)); | ||
| } | ||
|
||
|
|
||
| const auto retType = expr->getDirectCallee()->getReturnType(); | ||
| return createImageSample( | ||
| retType, imageType, sampledImage, /*sampler*/ nullptr, coordinate, | ||
| /*compareVal*/ nullptr, /*bias*/ nullptr, | ||
| /*lod*/ nullptr, {nullptr, nullptr}, constOffset, varOffset, | ||
| /*constOffsets*/ nullptr, /*sample*/ nullptr, | ||
| /*minLod*/ clamp, status, loc, range); | ||
| } | ||
|
|
||
| auto *image = loadIfGLValue(imageExpr); | ||
| auto *sampler = doExpr(expr->getArg(0)); | ||
| auto *coordinate = doExpr(expr->getArg(1)); | ||
| // .Sample()/.Gather() may have a third optional paramter for offset. | ||
| SpirvInstruction *constOffset = nullptr, *varOffset = nullptr; | ||
|
|
||
| const bool hasStatusArg = | ||
| expr->getArg(numArgs - 1)->getType()->isUnsignedIntegerType(); | ||
|
|
||
|
|
@@ -5832,14 +5885,6 @@ SpirvEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr, | |
| // 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)); | ||
| // .Sample()/.Gather() may have a third optional paramter for offset. | ||
| SpirvInstruction *constOffset = nullptr, *varOffset = nullptr; | ||
| if (hasOffsetArg) | ||
| handleOffsetInMethodCall(expr, 2, &constOffset, &varOffset); | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.