From 9a502c0e10b0b512e22e5f6f70e6c6c3ac0aa4a7 Mon Sep 17 00:00:00 2001 From: Ehsan Date: Mon, 18 Dec 2017 10:26:59 -0500 Subject: [PATCH] [spirv] Fix image sample instruction return types. (#932) --- .../clang/include/clang/SPIRV/ModuleBuilder.h | 4 +- tools/clang/lib/SPIRV/SPIRVEmitter.cpp | 135 ++++++++++++------ tools/clang/lib/SPIRV/SPIRVEmitter.h | 24 ++++ .../texture.array.sample-bias.hlsl | 18 ++- .../texture.array.sample-grad.hlsl | 17 +++ .../texture.array.sample-level.hlsl | 16 +++ .../CodeGenSPIRV/texture.array.sample.hlsl | 16 +++ .../CodeGenSPIRV/texture.sample-bias.hlsl | 17 ++- .../CodeGenSPIRV/texture.sample-grad.hlsl | 16 +++ .../CodeGenSPIRV/texture.sample-level.hlsl | 16 +++ .../test/CodeGenSPIRV/texture.sample.hlsl | 19 ++- 11 files changed, 248 insertions(+), 50 deletions(-) diff --git a/tools/clang/include/clang/SPIRV/ModuleBuilder.h b/tools/clang/include/clang/SPIRV/ModuleBuilder.h index 6e697c206..259185895 100644 --- a/tools/clang/include/clang/SPIRV/ModuleBuilder.h +++ b/tools/clang/include/clang/SPIRV/ModuleBuilder.h @@ -180,8 +180,8 @@ public: /// residency code will also be emitted. uint32_t createImageSample(uint32_t texelType, uint32_t imageType, uint32_t image, uint32_t sampler, - uint32_t coordinate, uint32_t bias, - uint32_t compareVal, uint32_t lod, + uint32_t coordinate, uint32_t compareVal, + uint32_t bias, uint32_t lod, std::pair grad, uint32_t constOffset, uint32_t varOffset, uint32_t constOffsets, uint32_t sample, diff --git a/tools/clang/lib/SPIRV/SPIRVEmitter.cpp b/tools/clang/lib/SPIRV/SPIRVEmitter.cpp index 4a44fb341..efe1aa23b 100644 --- a/tools/clang/lib/SPIRV/SPIRVEmitter.cpp +++ b/tools/clang/lib/SPIRV/SPIRVEmitter.cpp @@ -2350,8 +2350,8 @@ uint32_t SPIRVEmitter::processTextureGatherCmp(const CXXMemberCallExpr *expr) { const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : 0; return theBuilder.createImageGather( - retType, imageType, image, sampler, coordinate, - /*component*/ 0, comparator, constOffset, varOffset, /*constOffsets*/ 0, + retType, imageType, image, sampler, coordinate, /*component*/ 0, + comparator, constOffset, varOffset, /*constOffsets*/ 0, /*sampleNumber*/ 0, status); } @@ -2390,9 +2390,6 @@ SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad( emitError("buffer/texture type unimplemented", object->getExprLoc()); return 0; } - const uint32_t resultTypeId = - elemCount == 1 ? elemTypeId - : theBuilder.getVecType(elemTypeId, elemCount); // OpImageFetch and OpImageRead can only fetch a vector of 4 elements. const uint32_t texelTypeId = theBuilder.getVecType(elemTypeId, 4u); @@ -2400,26 +2397,9 @@ SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad( doFetch, texelTypeId, type, objectId, locationId, lod, constOffset, varOffset, /*constOffsets*/ 0, sampleNumber, residencyCode); - uint32_t retVal = texel; // If the result type is a vec1, vec2, or vec3, some extra processing // (extraction) is required. - switch (elemCount) { - case 1: - retVal = theBuilder.createCompositeExtract(elemTypeId, texel, {0}); - break; - case 2: - retVal = theBuilder.createVectorShuffle(resultTypeId, texel, texel, {0, 1}); - break; - case 3: - retVal = - theBuilder.createVectorShuffle(resultTypeId, texel, texel, {0, 1, 2}); - break; - case 4: - break; - default: - llvm_unreachable("vector element count must be 1, 2, 3, or 4"); - } - + uint32_t retVal = extractVecFromVec4(texel, elemCount, elemTypeId); return SpirvEvalInfo(retVal).setRValue(); } @@ -2768,6 +2748,52 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr, return SpirvEvalInfo(retVal).setRValue(); } +uint32_t SPIRVEmitter::createImageSample( + QualType retType, uint32_t imageType, uint32_t image, uint32_t sampler, + uint32_t coordinate, uint32_t compareVal, uint32_t bias, uint32_t lod, + std::pair grad, uint32_t constOffset, + uint32_t varOffset, uint32_t constOffsets, uint32_t sample, uint32_t minLod, + uint32_t residencyCodeId) { + + const auto retTypeId = typeTranslator.translateType(retType); + + // SampleDref* instructions in SPIR-V always return a scalar. + // They also have the correct type in HLSL. + if (compareVal) { + return theBuilder.createImageSample(retTypeId, imageType, image, sampler, + coordinate, compareVal, bias, lod, grad, + constOffset, varOffset, constOffsets, + sample, minLod, residencyCodeId); + } + + // Non-Dref Sample instructions in SPIR-V must always return a vec4. + auto texelTypeId = retTypeId; + QualType elemType = {}; + uint32_t elemTypeId = 0; + uint32_t retVecSize = 0; + if (TypeTranslator::isVectorType(retType, &elemType, &retVecSize) && + retVecSize != 4) { + elemTypeId = typeTranslator.translateType(elemType); + texelTypeId = theBuilder.getVecType(elemTypeId, 4); + } else if (TypeTranslator::isScalarType(retType)) { + retVecSize = 1; + elemTypeId = typeTranslator.translateType(retType); + texelTypeId = theBuilder.getVecType(elemTypeId, 4); + } + + uint32_t retVal = theBuilder.createImageSample( + texelTypeId, imageType, image, sampler, coordinate, compareVal, bias, lod, + grad, constOffset, varOffset, constOffsets, sample, minLod, + residencyCodeId); + + // Extract smaller vector from the vec4 result if necessary. + if (texelTypeId != retTypeId) { + retVal = extractVecFromVec4(retVal, retVecSize, elemTypeId); + } + + return retVal; +} + uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr, const bool isSample) { // Signatures: @@ -2823,18 +2849,16 @@ uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr, if (hasOffsetArg) handleOffsetInMethodCall(expr, 2, &constOffset, &varOffset); - const auto retType = - typeTranslator.translateType(expr->getDirectCallee()->getReturnType()); - + const auto retType = expr->getDirectCallee()->getReturnType(); + const auto retTypeId = typeTranslator.translateType(retType); if (isSample) { - // TODO: Handle sparse cases for this method. - return theBuilder.createImageSample( + return createImageSample( retType, imageType, image, sampler, coordinate, /*compareVal*/ 0, /*bias*/ 0, /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0, /*sampleNumber*/ 0, /*minLod*/ clamp, status); } else { return theBuilder.createImageGather( - retType, imageType, image, sampler, coordinate, + retTypeId, imageType, image, sampler, coordinate, // .Gather() doc says we return four components of red data. theBuilder.getConstantInt32(0), /*compareVal*/ 0, constOffset, varOffset, /*constOffsets*/ 0, /*sampleNumber*/ 0, status); @@ -2909,13 +2933,12 @@ SPIRVEmitter::processTextureSampleBiasLevel(const CXXMemberCallExpr *expr, if (hasOffsetArg) handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset); - const auto retType = - typeTranslator.translateType(expr->getDirectCallee()->getReturnType()); + const auto retType = expr->getDirectCallee()->getReturnType(); - return theBuilder.createImageSample( - retType, imageType, image, sampler, coordinate, /*compareVal*/ 0, bias, - lod, std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0, - /*sampleNumber*/ 0, /*minLod*/ clamp, status); + return createImageSample(retType, imageType, image, sampler, coordinate, + /*compareVal*/ 0, bias, lod, std::make_pair(0, 0), + constOffset, varOffset, /*constOffsets*/ 0, + /*sampleNumber*/ 0, /*minLod*/ clamp, status); } uint32_t SPIRVEmitter::processTextureSampleGrad(const CXXMemberCallExpr *expr) { @@ -2965,10 +2988,8 @@ uint32_t SPIRVEmitter::processTextureSampleGrad(const CXXMemberCallExpr *expr) { if (hasOffsetArg) handleOffsetInMethodCall(expr, 4, &constOffset, &varOffset); - const auto retType = - typeTranslator.translateType(expr->getDirectCallee()->getReturnType()); - - return theBuilder.createImageSample( + const auto retType = expr->getDirectCallee()->getReturnType(); + return createImageSample( retType, imageType, image, sampler, coordinate, /*compareVal*/ 0, /*bias*/ 0, /*lod*/ 0, std::make_pair(ddx, ddy), constOffset, varOffset, /*constOffsets*/ 0, /*sampleNumber*/ 0, /*minLod*/ clamp, status); @@ -3051,14 +3072,13 @@ SPIRVEmitter::processTextureSampleCmpCmpLevelZero(const CXXMemberCallExpr *expr, handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset); const uint32_t lod = isCmp ? 0 : theBuilder.getConstantFloat32(0); - const auto retType = - typeTranslator.translateType(expr->getDirectCallee()->getReturnType()); + const auto retType = expr->getDirectCallee()->getReturnType(); const auto imageType = typeTranslator.translateType(imageExpr->getType()); - return theBuilder.createImageSample( - retType, imageType, image, sampler, coordinate, compareVal, /*bias*/ 0, - lod, std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0, - /*sampleNumber*/ 0, /*minLod*/ clamp, status); + return createImageSample(retType, imageType, image, sampler, coordinate, + compareVal, /*bias*/ 0, lod, std::make_pair(0, 0), + constOffset, varOffset, /*constOffsets*/ 0, + /*sampleNumber*/ 0, /*minLod*/ clamp, status); } SpirvEvalInfo @@ -7265,5 +7285,30 @@ void SPIRVEmitter::processSwitchStmtUsingIfStmts(const SwitchStmt *switchStmt) { doStmt(defaultBody); } +uint32_t SPIRVEmitter::extractVecFromVec4(uint32_t fromId, + uint32_t targetVecSize, + uint32_t targetElemTypeId) { + assert(targetVecSize > 0 && targetVecSize < 5); + const uint32_t retType = + targetVecSize == 1 + ? targetElemTypeId + : theBuilder.getVecType(targetElemTypeId, targetVecSize); + switch (targetVecSize) { + case 1: + return theBuilder.createCompositeExtract(retType, fromId, {0}); + break; + case 2: + return theBuilder.createVectorShuffle(retType, fromId, fromId, {0, 1}); + break; + case 3: + return theBuilder.createVectorShuffle(retType, fromId, fromId, {0, 1, 2}); + break; + case 4: + return fromId; + default: + llvm_unreachable("vector element count must be 1, 2, 3, or 4"); + } +} + } // end namespace spirv } // end namespace clang diff --git a/tools/clang/lib/SPIRV/SPIRVEmitter.h b/tools/clang/lib/SPIRV/SPIRVEmitter.h index 194eb9394..adf5e8c3c 100644 --- a/tools/clang/lib/SPIRV/SPIRVEmitter.h +++ b/tools/clang/lib/SPIRV/SPIRVEmitter.h @@ -674,6 +674,30 @@ private: /// primitive in GS. uint32_t processStreamOutputRestart(const CXXMemberCallExpr *expr); +private: + /// \brief Takes a vector of size 4, and returns a vector of size 1 or 2 or 3 + /// or 4. Creates a CompositeExtract or VectorShuffle instruction to extract + /// a scalar or smaller vector from the beginning of the input vector if + /// necessary. Assumes that 'fromId' is the of a vector of size 4. + /// Panics if the target vector size is not 1, 2, 3, or 4. + uint32_t extractVecFromVec4(uint32_t fromId, uint32_t targetVecSize, + uint32_t targetElemTypeId); + + /// \brief Creates SPIR-V instructions for sampling the given image. + /// It utilizes the ModuleBuilder's createImageSample and it ensures that the + /// returned type is handled correctly. + /// HLSL image sampling methods may return a scalar, vec1, vec2, vec3, or + /// vec4. But non-Dref image sampling instructions in SPIR-V must always + /// return a vec4. As a result, an extra processing step is necessary. + uint32_t createImageSample(QualType retType, uint32_t imageType, + uint32_t image, uint32_t sampler, + uint32_t coordinate, uint32_t compareVal, + uint32_t bias, uint32_t lod, + std::pair grad, + uint32_t constOffset, uint32_t varOffset, + uint32_t constOffsets, uint32_t sample, + uint32_t minLod, uint32_t residencyCodeId); + private: /// \brief Wrapper method to create a fatal error message and report it /// in the diagnostic engine associated with this consumer. diff --git a/tools/clang/test/CodeGenSPIRV/texture.array.sample-bias.hlsl b/tools/clang/test/CodeGenSPIRV/texture.array.sample-bias.hlsl index 00884c927..a7f0c989b 100644 --- a/tools/clang/test/CodeGenSPIRV/texture.array.sample-bias.hlsl +++ b/tools/clang/test/CodeGenSPIRV/texture.array.sample-bias.hlsl @@ -7,6 +7,8 @@ SamplerState gSampler : register(s5); Texture1DArray t1 : register(t1); Texture2DArray t2 : register(t2); TextureCubeArray t3 : register(t3); +Texture2DArray t4 : register(t4); +TextureCubeArray t5 : register(t5); // CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability MinLod @@ -77,6 +79,20 @@ float4 main(int2 offset : A) : SV_Target { // CHECK-NEXT: [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 // CHECK-NEXT: OpStore %val7 [[result]] float4 val7 = t3.SampleBias(gSampler, float4(0.1, 0.2, 0.3, 1), 0.5, /*clamp*/ 2.5f, status); - + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// Make sure OpImageSampleImplicitLod returns a vec4. +// Make sure OpImageSparseSampleImplicitLod returns a struct, in which the second member is a vec4. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +// CHECK: [[v4result:%\d+]] = OpImageSampleImplicitLod %v4float {{%\d+}} {{%\d+}} Bias|Offset %float_0_5 {{%\d+}} +// CHECK: {{%\d+}} = OpCompositeExtract %float [[v4result]] 0 + float val8 = t4.SampleBias(gSampler, float3(0.1, 0.2, 1), 0.5, offset); + +// CHECK: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Bias|MinLod %float_0_5 %float_2_5 +// CHECK: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 +// CHECK: {{%\d+}} = OpVectorShuffle %v3float [[v4result]] [[v4result]] 0 1 2 + float3 val9 = t5.SampleBias(gSampler, float4(0.1, 0.2, 0.3, 1), 0.5, /*clamp*/ 2.5f, status); + return 1.0; } diff --git a/tools/clang/test/CodeGenSPIRV/texture.array.sample-grad.hlsl b/tools/clang/test/CodeGenSPIRV/texture.array.sample-grad.hlsl index 785ca000d..43384ea56 100644 --- a/tools/clang/test/CodeGenSPIRV/texture.array.sample-grad.hlsl +++ b/tools/clang/test/CodeGenSPIRV/texture.array.sample-grad.hlsl @@ -7,6 +7,9 @@ SamplerState gSampler : register(s5); Texture1DArray t1 : register(t1); Texture2DArray t2 : register(t2); TextureCubeArray t3 : register(t3); +Texture2DArray t4 : register(t4); +TextureCubeArray t5 : register(t5); + // CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability MinLod @@ -84,5 +87,19 @@ float4 main(int2 offset : A) : SV_Target { // CHECK-NEXT: OpStore %val7 [[result]] float4 val7 = t3.SampleGrad(gSampler, float4(0.1, 0.1, 0.1, 0.1), float3(0.2, 0.2, 0.2), float3(0.3, 0.3, 0.3), clamp, status); +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// Make sure OpImageSampleExplicitLod returns a vec4. +// Make sure OpImageSparseSampleExplicitLod returns a struct, in which the second member is a vec4. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Grad|Offset {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: {{%\d+}} = OpCompositeExtract %float [[v4result]] 0 + float val8 = t4.SampleGrad(gSampler, float3(0.1, 0.1, 0.1), float2(0.2, 0.2), float2(0.3, 0.3), offset); + +// CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Grad|MinLod {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 +// CHECK: {{%\d+}} = OpVectorShuffle %v2float [[v4result]] [[v4result]] 0 1 + float2 val9 = t5.SampleGrad(gSampler, float4(0.1, 0.1, 0.1, 0.1), float3(0.2, 0.2, 0.2), float3(0.3, 0.3, 0.3), clamp, status); + return 1.0; } diff --git a/tools/clang/test/CodeGenSPIRV/texture.array.sample-level.hlsl b/tools/clang/test/CodeGenSPIRV/texture.array.sample-level.hlsl index 8d71ec8d1..897ef7b87 100644 --- a/tools/clang/test/CodeGenSPIRV/texture.array.sample-level.hlsl +++ b/tools/clang/test/CodeGenSPIRV/texture.array.sample-level.hlsl @@ -7,6 +7,8 @@ SamplerState gSampler : register(s5); Texture1DArray t1 : register(t1); Texture2DArray t2 : register(t2); TextureCubeArray t3 : register(t3); +Texture2DArray t4 : register(t4); +TextureCubeArray t5 : register(t5); // CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability SparseResidency @@ -63,5 +65,19 @@ float4 main(int2 offset : A) : SV_Target { // CHECK-NEXT: OpStore %val5 [[result]] float4 val5 = t3.SampleLevel(gSampler, float4(0.1, 0.2, 0.3, 1), 30, status); +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// Make sure OpImageSampleExplicitLod returns a vec4. +// Make sure OpImageSparseSampleExplicitLod returns a struct, in which the second member is a vec4. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|Offset %float_20 {{%\d+}} +// CHECK: {{%\d+}} = OpCompositeExtract %float [[v4result]] 0 + float val6 = t4.SampleLevel(gSampler, float3(0.1, 0.2, 1), 20, offset); + +// CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Lod %float_30 +// CHECK: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 +// CHECK: {{%\d+}} = OpVectorShuffle %v3float [[v4result]] [[v4result]] 0 1 2 + float3 val7 = t5.SampleLevel(gSampler, float4(0.1, 0.2, 0.3, 1), 30, status); + return 1.0; } diff --git a/tools/clang/test/CodeGenSPIRV/texture.array.sample.hlsl b/tools/clang/test/CodeGenSPIRV/texture.array.sample.hlsl index 6a52a0047..bdda311d0 100644 --- a/tools/clang/test/CodeGenSPIRV/texture.array.sample.hlsl +++ b/tools/clang/test/CodeGenSPIRV/texture.array.sample.hlsl @@ -7,6 +7,8 @@ SamplerState gSampler : register(s5); Texture1DArray t1 : register(t1); Texture2DArray t2 : register(t2); TextureCubeArray t3 : register(t3); +Texture1DArray t4 : register(t4); +TextureCubeArray t5 : register(t5); // CHECK: OpCapability MinLod // CHECK: OpCapability SparseResidency @@ -76,5 +78,19 @@ float4 main() : SV_Target { // CHECK-NEXT: OpStore %val7 [[result]] float4 val7 = t3.Sample(gSampler, float4(0.1, 0.2, 0.3, 1), /*clamp*/ 1.5, status); +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// Make sure OpImageSampleImplicitLod returns a vec4. +// Make sure OpImageSparseSampleImplicitLod returns a struct, in which the second member is a vec4. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +// CHECK: [[v4result:%\d+]] = OpImageSampleImplicitLod %v4float {{%\d+}} {{%\d+}} ConstOffset %int_1 +// CHECK: {{%\d+}} = OpCompositeExtract %float [[v4result]] 0 + float val8 = t4.Sample(gSampler, float2(0.1, 1), 1); + +// CHECK: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} MinLod %float_1_5 +// CHECK: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 +// CHECK: {{%\d+}} = OpVectorShuffle %v3float [[v4result]] [[v4result]] 0 1 2 + float3 val9 = t5.Sample(gSampler, float4(0.1, 0.2, 0.3, 1), /*clamp*/ 1.5, status); + return 1.0; } diff --git a/tools/clang/test/CodeGenSPIRV/texture.sample-bias.hlsl b/tools/clang/test/CodeGenSPIRV/texture.sample-bias.hlsl index bb7fdcde2..ee010d9a9 100644 --- a/tools/clang/test/CodeGenSPIRV/texture.sample-bias.hlsl +++ b/tools/clang/test/CodeGenSPIRV/texture.sample-bias.hlsl @@ -8,6 +8,8 @@ Texture1D t1 : register(t1); Texture2D t2 : register(t2); Texture3D t3 : register(t3); TextureCube t4 : register(t4); +Texture1D t5 : register(t5); +Texture3D t6 : register(t6); // CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability MinLod @@ -88,6 +90,19 @@ float4 main(int3 offset: A) : SV_Target { // CHECK-NEXT: OpStore %val8 [[result]] float4 val8 = t4.SampleBias(gSampler, float3(0.1, 0.2, 0.3), 0.5, /*clamp*/ 2.5, status); +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// Make sure OpImageSampleImplicitLod returns a vec4. +// Make sure OpImageSparseSampleImplicitLod returns a struct, in which the second member is a vec4. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +// CHECK: [[v4result:%\d+]] = OpImageSampleImplicitLod %v4float {{%\d+}} %float_0_1 Bias %float_0_5 +// CHECK: {{%\d+}} = OpCompositeExtract %float [[v4result]] 0 + float val9 = t5.SampleBias(gSampler, 0.1, 0.5); + +// CHECK: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Bias|Offset|MinLod %float_0_5 {{%\d+}} {{%\d+}} +// CHECK: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 +// CHECK: {{%\d+}} = OpVectorShuffle %v2float [[v4result]] [[v4result]] 0 1 + float2 val10 = t6.SampleBias(gSampler, float3(0.1, 0.2, 0.3), 0.5, offset, clamp, status); + return 1.0; } -// CHECK-WHOLE-SPIR-V: \ No newline at end of file diff --git a/tools/clang/test/CodeGenSPIRV/texture.sample-grad.hlsl b/tools/clang/test/CodeGenSPIRV/texture.sample-grad.hlsl index d336e6695..f8fe49c3c 100644 --- a/tools/clang/test/CodeGenSPIRV/texture.sample-grad.hlsl +++ b/tools/clang/test/CodeGenSPIRV/texture.sample-grad.hlsl @@ -8,6 +8,8 @@ Texture1D t1 : register(t1); Texture2D t2 : register(t2); Texture3D t3 : register(t3); TextureCube t4 : register(t4); +Texture1D t5 : register(t5); +Texture2D t6 : register(t6); // CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability MinLod @@ -92,5 +94,19 @@ float4 main(int2 offset : A) : SV_Target { // CHECK-NEXT: OpStore %val8 [[result]] float4 val8 = t4.SampleGrad(gSampler, float3(0.1, 0.1, 0.1), float3(0.2, 0.2, 0.2), float3(0.3, 0.3, 0.3), /*clamp*/3.5, status); +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// Make sure OpImageSampleExplicitLod returns a vec4. +// Make sure OpImageSparseSampleExplicitLod returns a struct, in which the second member is a vec4. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} %float_0_1 Grad %float_0_2 %float_0_3 +// CHECK: {{%\d+}} = OpCompositeExtract %float [[v4result]] 0 + float val9 = t5.SampleGrad(gSampler, 0.1, 0.2, 0.3); + +// CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Grad|Offset|MinLod {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 +// CHECK: {{%\d+}} = OpVectorShuffle %v2float [[v4result]] [[v4result]] 0 1 + float2 val10 = t6.SampleGrad(gSampler, float2(0.1, 0.1), float2(0.2, 0.2), float2(0.3, 0.3), offset, clamp, status); + return 1.0; } diff --git a/tools/clang/test/CodeGenSPIRV/texture.sample-level.hlsl b/tools/clang/test/CodeGenSPIRV/texture.sample-level.hlsl index 18c22a751..2d88ed895 100644 --- a/tools/clang/test/CodeGenSPIRV/texture.sample-level.hlsl +++ b/tools/clang/test/CodeGenSPIRV/texture.sample-level.hlsl @@ -8,6 +8,8 @@ Texture1D t1 : register(t1); Texture2D t2 : register(t2); Texture3D t3 : register(t3); TextureCube t4 : register(t4); +Texture3D t5 : register(t5); +TextureCube t6 : register(t6); // CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability SparseResidency @@ -71,5 +73,19 @@ float4 main(int3 offset: A) : SV_Target { // CHECK-NEXT: OpStore %val6 [[result]] float4 val6 = t4.SampleLevel(gSampler, float3(0.1, 0.2, 0.3), 10, status); +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// Make sure OpImageSampleExplicitLod returns a vec4. +// Make sure OpImageSparseSampleExplicitLod returns a struct, in which the second member is a vec4. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|Offset %float_10 {{%\d+}} +// CHECK: {{%\d+}} = OpCompositeExtract %float [[v4result]] 0 + float val7 = t5.SampleLevel(gSampler, float3(0.1, 0.2, 0.3), 10, offset); + +// CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Lod %float_10 +// CHECK: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 +// CHECK: {{%\d+}} = OpVectorShuffle %v2float [[v4result]] [[v4result]] 0 1 + float2 val8 = t6.SampleLevel(gSampler, float3(0.1, 0.2, 0.3), 10, status); + return 1.0; } diff --git a/tools/clang/test/CodeGenSPIRV/texture.sample.hlsl b/tools/clang/test/CodeGenSPIRV/texture.sample.hlsl index 1e9b72a16..b1fdb8838 100644 --- a/tools/clang/test/CodeGenSPIRV/texture.sample.hlsl +++ b/tools/clang/test/CodeGenSPIRV/texture.sample.hlsl @@ -8,6 +8,8 @@ Texture1D t1 : register(t1); Texture2D t2 : register(t2); Texture3D t3 : register(t3); TextureCube t4 : register(t4); +Texture1D t5 : register(t5); +TextureCube t6 : register(t6); // CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability MinLod @@ -87,6 +89,21 @@ float4 main(int2 offset: A) : SV_Target { // CHECK-NEXT: [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 // CHECK-NEXT: OpStore %val8 [[result]] float4 val8 = t4.Sample(gSampler, float3(0.1, 0.2, 0.3), /*clamp*/ 2.0f, status); - + + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// Make sure OpImageSampleImplicitLod returns a vec4. +// Make sure OpImageSparseSampleImplicitLod returns a struct, in which the second member is a vec4. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +// CHECK: [[v4result:%\d+]] = OpImageSampleImplicitLod %v4float {{%\d+}} %float_0_1 None +// CHECK: {{%\d+}} = OpCompositeExtract %float [[v4result]] 0 + float val9 = t5.Sample(gSampler, 0.1); + +// CHECK: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} MinLod %float_2 +// CHECK: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1 +// CHECK: {{%\d+}} = OpVectorShuffle %v3float [[v4result]] [[v4result]] 0 1 2 + float3 val10 = t6.Sample(gSampler, float3(0.1, 0.2, 0.3), /*clamp*/ 2.0f, status); + return 1.0; }