[spirv] Fix image sample instruction return types. (#932)
This commit is contained in:
Родитель
1a45ed822a
Коммит
9a502c0e10
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче