[spirv] Fix image sample instruction return types. (#932)

This commit is contained in:
Ehsan 2017-12-18 10:26:59 -05:00 коммит произвёл GitHub
Родитель 1a45ed822a
Коммит 9a502c0e10
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 248 добавлений и 50 удалений

Просмотреть файл

@ -180,8 +180,8 @@ public:
/// residency code will also be emitted. /// residency code will also be emitted.
uint32_t createImageSample(uint32_t texelType, uint32_t imageType, uint32_t createImageSample(uint32_t texelType, uint32_t imageType,
uint32_t image, uint32_t sampler, uint32_t image, uint32_t sampler,
uint32_t coordinate, uint32_t bias, uint32_t coordinate, uint32_t compareVal,
uint32_t compareVal, uint32_t lod, uint32_t bias, uint32_t lod,
std::pair<uint32_t, uint32_t> grad, std::pair<uint32_t, uint32_t> grad,
uint32_t constOffset, uint32_t varOffset, uint32_t constOffset, uint32_t varOffset,
uint32_t constOffsets, uint32_t sample, uint32_t constOffsets, uint32_t sample,

Просмотреть файл

@ -2350,8 +2350,8 @@ uint32_t SPIRVEmitter::processTextureGatherCmp(const CXXMemberCallExpr *expr) {
const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : 0; const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : 0;
return theBuilder.createImageGather( return theBuilder.createImageGather(
retType, imageType, image, sampler, coordinate, retType, imageType, image, sampler, coordinate, /*component*/ 0,
/*component*/ 0, comparator, constOffset, varOffset, /*constOffsets*/ 0, comparator, constOffset, varOffset, /*constOffsets*/ 0,
/*sampleNumber*/ 0, status); /*sampleNumber*/ 0, status);
} }
@ -2390,9 +2390,6 @@ SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(
emitError("buffer/texture type unimplemented", object->getExprLoc()); emitError("buffer/texture type unimplemented", object->getExprLoc());
return 0; return 0;
} }
const uint32_t resultTypeId =
elemCount == 1 ? elemTypeId
: theBuilder.getVecType(elemTypeId, elemCount);
// OpImageFetch and OpImageRead can only fetch a vector of 4 elements. // OpImageFetch and OpImageRead can only fetch a vector of 4 elements.
const uint32_t texelTypeId = theBuilder.getVecType(elemTypeId, 4u); const uint32_t texelTypeId = theBuilder.getVecType(elemTypeId, 4u);
@ -2400,26 +2397,9 @@ SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(
doFetch, texelTypeId, type, objectId, locationId, lod, constOffset, doFetch, texelTypeId, type, objectId, locationId, lod, constOffset,
varOffset, /*constOffsets*/ 0, sampleNumber, residencyCode); varOffset, /*constOffsets*/ 0, sampleNumber, residencyCode);
uint32_t retVal = texel;
// If the result type is a vec1, vec2, or vec3, some extra processing // If the result type is a vec1, vec2, or vec3, some extra processing
// (extraction) is required. // (extraction) is required.
switch (elemCount) { uint32_t retVal = extractVecFromVec4(texel, elemCount, elemTypeId);
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");
}
return SpirvEvalInfo(retVal).setRValue(); return SpirvEvalInfo(retVal).setRValue();
} }
@ -2768,6 +2748,52 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
return SpirvEvalInfo(retVal).setRValue(); 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<uint32_t, uint32_t> 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, uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
const bool isSample) { const bool isSample) {
// Signatures: // Signatures:
@ -2823,18 +2849,16 @@ uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
if (hasOffsetArg) if (hasOffsetArg)
handleOffsetInMethodCall(expr, 2, &constOffset, &varOffset); handleOffsetInMethodCall(expr, 2, &constOffset, &varOffset);
const auto retType = const auto retType = expr->getDirectCallee()->getReturnType();
typeTranslator.translateType(expr->getDirectCallee()->getReturnType()); const auto retTypeId = typeTranslator.translateType(retType);
if (isSample) { if (isSample) {
// TODO: Handle sparse cases for this method. return createImageSample(
return theBuilder.createImageSample(
retType, imageType, image, sampler, coordinate, /*compareVal*/ 0, retType, imageType, image, sampler, coordinate, /*compareVal*/ 0,
/*bias*/ 0, /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset, /*bias*/ 0, /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset,
/*constOffsets*/ 0, /*sampleNumber*/ 0, /*minLod*/ clamp, status); /*constOffsets*/ 0, /*sampleNumber*/ 0, /*minLod*/ clamp, status);
} else { } else {
return theBuilder.createImageGather( return theBuilder.createImageGather(
retType, imageType, image, sampler, coordinate, retTypeId, imageType, image, sampler, coordinate,
// .Gather() doc says we return four components of red data. // .Gather() doc says we return four components of red data.
theBuilder.getConstantInt32(0), /*compareVal*/ 0, constOffset, theBuilder.getConstantInt32(0), /*compareVal*/ 0, constOffset,
varOffset, /*constOffsets*/ 0, /*sampleNumber*/ 0, status); varOffset, /*constOffsets*/ 0, /*sampleNumber*/ 0, status);
@ -2909,13 +2933,12 @@ SPIRVEmitter::processTextureSampleBiasLevel(const CXXMemberCallExpr *expr,
if (hasOffsetArg) if (hasOffsetArg)
handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset); handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
const auto retType = const auto retType = expr->getDirectCallee()->getReturnType();
typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
return theBuilder.createImageSample( return createImageSample(retType, imageType, image, sampler, coordinate,
retType, imageType, image, sampler, coordinate, /*compareVal*/ 0, bias, /*compareVal*/ 0, bias, lod, std::make_pair(0, 0),
lod, std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0, constOffset, varOffset, /*constOffsets*/ 0,
/*sampleNumber*/ 0, /*minLod*/ clamp, status); /*sampleNumber*/ 0, /*minLod*/ clamp, status);
} }
uint32_t SPIRVEmitter::processTextureSampleGrad(const CXXMemberCallExpr *expr) { uint32_t SPIRVEmitter::processTextureSampleGrad(const CXXMemberCallExpr *expr) {
@ -2965,10 +2988,8 @@ uint32_t SPIRVEmitter::processTextureSampleGrad(const CXXMemberCallExpr *expr) {
if (hasOffsetArg) if (hasOffsetArg)
handleOffsetInMethodCall(expr, 4, &constOffset, &varOffset); handleOffsetInMethodCall(expr, 4, &constOffset, &varOffset);
const auto retType = const auto retType = expr->getDirectCallee()->getReturnType();
typeTranslator.translateType(expr->getDirectCallee()->getReturnType()); return createImageSample(
return theBuilder.createImageSample(
retType, imageType, image, sampler, coordinate, /*compareVal*/ 0, retType, imageType, image, sampler, coordinate, /*compareVal*/ 0,
/*bias*/ 0, /*lod*/ 0, std::make_pair(ddx, ddy), constOffset, varOffset, /*bias*/ 0, /*lod*/ 0, std::make_pair(ddx, ddy), constOffset, varOffset,
/*constOffsets*/ 0, /*sampleNumber*/ 0, /*minLod*/ clamp, status); /*constOffsets*/ 0, /*sampleNumber*/ 0, /*minLod*/ clamp, status);
@ -3051,14 +3072,13 @@ SPIRVEmitter::processTextureSampleCmpCmpLevelZero(const CXXMemberCallExpr *expr,
handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset); handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
const uint32_t lod = isCmp ? 0 : theBuilder.getConstantFloat32(0); const uint32_t lod = isCmp ? 0 : theBuilder.getConstantFloat32(0);
const auto retType = const auto retType = expr->getDirectCallee()->getReturnType();
typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
const auto imageType = typeTranslator.translateType(imageExpr->getType()); const auto imageType = typeTranslator.translateType(imageExpr->getType());
return theBuilder.createImageSample( return createImageSample(retType, imageType, image, sampler, coordinate,
retType, imageType, image, sampler, coordinate, compareVal, /*bias*/ 0, compareVal, /*bias*/ 0, lod, std::make_pair(0, 0),
lod, std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0, constOffset, varOffset, /*constOffsets*/ 0,
/*sampleNumber*/ 0, /*minLod*/ clamp, status); /*sampleNumber*/ 0, /*minLod*/ clamp, status);
} }
SpirvEvalInfo SpirvEvalInfo
@ -7265,5 +7285,30 @@ void SPIRVEmitter::processSwitchStmtUsingIfStmts(const SwitchStmt *switchStmt) {
doStmt(defaultBody); 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 spirv
} // end namespace clang } // end namespace clang

Просмотреть файл

@ -674,6 +674,30 @@ private:
/// primitive in GS. /// primitive in GS.
uint32_t processStreamOutputRestart(const CXXMemberCallExpr *expr); 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 <result-id> 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<uint32_t, uint32_t> grad,
uint32_t constOffset, uint32_t varOffset,
uint32_t constOffsets, uint32_t sample,
uint32_t minLod, uint32_t residencyCodeId);
private: private:
/// \brief Wrapper method to create a fatal error message and report it /// \brief Wrapper method to create a fatal error message and report it
/// in the diagnostic engine associated with this consumer. /// in the diagnostic engine associated with this consumer.

Просмотреть файл

@ -7,6 +7,8 @@ SamplerState gSampler : register(s5);
Texture1DArray <float4> t1 : register(t1); Texture1DArray <float4> t1 : register(t1);
Texture2DArray <float4> t2 : register(t2); Texture2DArray <float4> t2 : register(t2);
TextureCubeArray <float4> t3 : register(t3); TextureCubeArray <float4> t3 : register(t3);
Texture2DArray <float> t4 : register(t4);
TextureCubeArray <float3> t5 : register(t5);
// CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability ImageGatherExtended
// CHECK: OpCapability MinLod // CHECK: OpCapability MinLod
@ -78,5 +80,19 @@ float4 main(int2 offset : A) : SV_Target {
// CHECK-NEXT: OpStore %val7 [[result]] // CHECK-NEXT: OpStore %val7 [[result]]
float4 val7 = t3.SampleBias(gSampler, float4(0.1, 0.2, 0.3, 1), 0.5, /*clamp*/ 2.5f, status); 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; return 1.0;
} }

Просмотреть файл

@ -7,6 +7,9 @@ SamplerState gSampler : register(s5);
Texture1DArray <float4> t1 : register(t1); Texture1DArray <float4> t1 : register(t1);
Texture2DArray <float4> t2 : register(t2); Texture2DArray <float4> t2 : register(t2);
TextureCubeArray <float4> t3 : register(t3); TextureCubeArray <float4> t3 : register(t3);
Texture2DArray <float> t4 : register(t4);
TextureCubeArray <float2> t5 : register(t5);
// CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability ImageGatherExtended
// CHECK: OpCapability MinLod // CHECK: OpCapability MinLod
@ -84,5 +87,19 @@ float4 main(int2 offset : A) : SV_Target {
// CHECK-NEXT: OpStore %val7 [[result]] // 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); 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; return 1.0;
} }

Просмотреть файл

@ -7,6 +7,8 @@ SamplerState gSampler : register(s5);
Texture1DArray <float4> t1 : register(t1); Texture1DArray <float4> t1 : register(t1);
Texture2DArray <float4> t2 : register(t2); Texture2DArray <float4> t2 : register(t2);
TextureCubeArray <float4> t3 : register(t3); TextureCubeArray <float4> t3 : register(t3);
Texture2DArray <float> t4 : register(t4);
TextureCubeArray <float3> t5 : register(t5);
// CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability ImageGatherExtended
// CHECK: OpCapability SparseResidency // CHECK: OpCapability SparseResidency
@ -63,5 +65,19 @@ float4 main(int2 offset : A) : SV_Target {
// CHECK-NEXT: OpStore %val5 [[result]] // CHECK-NEXT: OpStore %val5 [[result]]
float4 val5 = t3.SampleLevel(gSampler, float4(0.1, 0.2, 0.3, 1), 30, status); 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; return 1.0;
} }

Просмотреть файл

@ -7,6 +7,8 @@ SamplerState gSampler : register(s5);
Texture1DArray <float4> t1 : register(t1); Texture1DArray <float4> t1 : register(t1);
Texture2DArray <float4> t2 : register(t2); Texture2DArray <float4> t2 : register(t2);
TextureCubeArray <float4> t3 : register(t3); TextureCubeArray <float4> t3 : register(t3);
Texture1DArray <float> t4 : register(t4);
TextureCubeArray <float3> t5 : register(t5);
// CHECK: OpCapability MinLod // CHECK: OpCapability MinLod
// CHECK: OpCapability SparseResidency // CHECK: OpCapability SparseResidency
@ -76,5 +78,19 @@ float4 main() : SV_Target {
// CHECK-NEXT: OpStore %val7 [[result]] // CHECK-NEXT: OpStore %val7 [[result]]
float4 val7 = t3.Sample(gSampler, float4(0.1, 0.2, 0.3, 1), /*clamp*/ 1.5, status); 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; return 1.0;
} }

Просмотреть файл

@ -8,6 +8,8 @@ Texture1D <float4> t1 : register(t1);
Texture2D <float4> t2 : register(t2); Texture2D <float4> t2 : register(t2);
Texture3D <float4> t3 : register(t3); Texture3D <float4> t3 : register(t3);
TextureCube <float4> t4 : register(t4); TextureCube <float4> t4 : register(t4);
Texture1D <float> t5 : register(t5);
Texture3D <float2> t6 : register(t6);
// CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability ImageGatherExtended
// CHECK: OpCapability MinLod // CHECK: OpCapability MinLod
@ -88,6 +90,19 @@ float4 main(int3 offset: A) : SV_Target {
// CHECK-NEXT: OpStore %val8 [[result]] // CHECK-NEXT: OpStore %val8 [[result]]
float4 val8 = t4.SampleBias(gSampler, float3(0.1, 0.2, 0.3), 0.5, /*clamp*/ 2.5, status); 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; return 1.0;
} }
// CHECK-WHOLE-SPIR-V:

Просмотреть файл

@ -8,6 +8,8 @@ Texture1D <float4> t1 : register(t1);
Texture2D <float4> t2 : register(t2); Texture2D <float4> t2 : register(t2);
Texture3D <float4> t3 : register(t3); Texture3D <float4> t3 : register(t3);
TextureCube <float4> t4 : register(t4); TextureCube <float4> t4 : register(t4);
Texture1D <float> t5 : register(t5);
Texture2D <float2> t6 : register(t6);
// CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability ImageGatherExtended
// CHECK: OpCapability MinLod // CHECK: OpCapability MinLod
@ -92,5 +94,19 @@ float4 main(int2 offset : A) : SV_Target {
// CHECK-NEXT: OpStore %val8 [[result]] // 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); 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; return 1.0;
} }

Просмотреть файл

@ -8,6 +8,8 @@ Texture1D <float4> t1 : register(t1);
Texture2D <float4> t2 : register(t2); Texture2D <float4> t2 : register(t2);
Texture3D <float4> t3 : register(t3); Texture3D <float4> t3 : register(t3);
TextureCube <float4> t4 : register(t4); TextureCube <float4> t4 : register(t4);
Texture3D <float> t5 : register(t5);
TextureCube <float2> t6 : register(t6);
// CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability ImageGatherExtended
// CHECK: OpCapability SparseResidency // CHECK: OpCapability SparseResidency
@ -71,5 +73,19 @@ float4 main(int3 offset: A) : SV_Target {
// CHECK-NEXT: OpStore %val6 [[result]] // CHECK-NEXT: OpStore %val6 [[result]]
float4 val6 = t4.SampleLevel(gSampler, float3(0.1, 0.2, 0.3), 10, status); 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; return 1.0;
} }

Просмотреть файл

@ -8,6 +8,8 @@ Texture1D <float4> t1 : register(t1);
Texture2D <float4> t2 : register(t2); Texture2D <float4> t2 : register(t2);
Texture3D <float4> t3 : register(t3); Texture3D <float4> t3 : register(t3);
TextureCube <float4> t4 : register(t4); TextureCube <float4> t4 : register(t4);
Texture1D <float> t5 : register(t5);
TextureCube <float3> t6 : register(t6);
// CHECK: OpCapability ImageGatherExtended // CHECK: OpCapability ImageGatherExtended
// CHECK: OpCapability MinLod // CHECK: OpCapability MinLod
@ -88,5 +90,20 @@ float4 main(int2 offset: A) : SV_Target {
// CHECK-NEXT: OpStore %val8 [[result]] // CHECK-NEXT: OpStore %val8 [[result]]
float4 val8 = t4.Sample(gSampler, float3(0.1, 0.2, 0.3), /*clamp*/ 2.0f, status); 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; return 1.0;
} }