|
@@ -2296,31 +2296,11 @@ uint32_t SPIRVEmitter::processTextureGatherRGBACmpRGBA(
|
|
offsetType, {offset0, offset1, offset2, offset3});
|
|
offsetType, {offset0, offset1, offset2, offset3});
|
|
}
|
|
}
|
|
|
|
|
|
- if (!hasStatusArg)
|
|
|
|
- return theBuilder.createImageGather(
|
|
|
|
- retTypeId, imageTypeId, image, sampler, coordinate,
|
|
|
|
- theBuilder.getConstantInt32(component), compareVal, constOffset,
|
|
|
|
- varOffset, constOffsets, /*sampleNumber*/ 0, /*isSparse*/ false);
|
|
|
|
-
|
|
|
|
- // If the Status parameter is present, OpImageSparseGather should be used.
|
|
|
|
- // The result type of this SPIR-V instruction is a struct in which the first
|
|
|
|
- // member is an integer that holds the Residency Code.
|
|
|
|
- const auto uintType = theBuilder.getUint32Type();
|
|
|
|
- const auto sparseRetType =
|
|
|
|
- theBuilder.getStructType({uintType, retTypeId}, "SparseResidencyStruct",
|
|
|
|
- {"Residency.Code", "Result.Type"});
|
|
|
|
-
|
|
|
|
- // Perform ImageSparseGather
|
|
|
|
- const auto sparseGather = theBuilder.createImageGather(
|
|
|
|
- sparseRetType, imageTypeId, image, sampler, coordinate,
|
|
|
|
|
|
+ const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : 0;
|
|
|
|
+ return theBuilder.createImageGather(
|
|
|
|
+ retTypeId, imageTypeId, image, sampler, coordinate,
|
|
theBuilder.getConstantInt32(component), compareVal, constOffset,
|
|
theBuilder.getConstantInt32(component), compareVal, constOffset,
|
|
- varOffset, constOffsets, /*sampleNumber*/ 0, /*isSparse*/ true);
|
|
|
|
- // Write the Residency Code
|
|
|
|
- const auto status =
|
|
|
|
- theBuilder.createCompositeExtract(uintType, sparseGather, {0});
|
|
|
|
- theBuilder.createStore(doExpr(expr->getArg(numArgs - 1)), status);
|
|
|
|
- // Return the results
|
|
|
|
- return theBuilder.createCompositeExtract(retTypeId, sparseGather, {1});
|
|
|
|
|
|
+ varOffset, constOffsets, /*sampleNumber*/ 0, status);
|
|
}
|
|
}
|
|
|
|
|
|
uint32_t SPIRVEmitter::processTextureGatherCmp(const CXXMemberCallExpr *expr) {
|
|
uint32_t SPIRVEmitter::processTextureGatherCmp(const CXXMemberCallExpr *expr) {
|
|
@@ -2362,32 +2342,12 @@ uint32_t SPIRVEmitter::processTextureGatherCmp(const CXXMemberCallExpr *expr) {
|
|
|
|
|
|
const auto retType = typeTranslator.translateType(callee->getReturnType());
|
|
const auto retType = typeTranslator.translateType(callee->getReturnType());
|
|
const auto imageType = typeTranslator.translateType(imageExpr->getType());
|
|
const auto imageType = typeTranslator.translateType(imageExpr->getType());
|
|
|
|
+ const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : 0;
|
|
|
|
|
|
- if(!hasStatusArg)
|
|
|
|
- return theBuilder.createImageGather(
|
|
|
|
- retType, imageType, image, sampler, coordinate,
|
|
|
|
- /*component*/ 0, comparator, constOffset, varOffset, /*constOffsets*/ 0,
|
|
|
|
- /*sampleNumber*/ 0, /*isSparse*/ false);
|
|
|
|
-
|
|
|
|
- // If the Status parameter is present, OpImageSparseGather should be used.
|
|
|
|
- // The result type of this SPIR-V instruction is a struct in which the first
|
|
|
|
- // member is an integer that holds the Residency Code.
|
|
|
|
- const auto uintType = theBuilder.getUint32Type();
|
|
|
|
- const auto sparseRetType =
|
|
|
|
- theBuilder.getStructType({uintType, retType}, "SparseResidencyStruct",
|
|
|
|
- {"Residency.Code", "Result.Type"});
|
|
|
|
-
|
|
|
|
- // Perform ImageSparseGather
|
|
|
|
- const auto sparseGather = theBuilder.createImageGather(
|
|
|
|
- sparseRetType, imageType, image, sampler, coordinate,
|
|
|
|
|
|
+ return theBuilder.createImageGather(
|
|
|
|
+ retType, imageType, image, sampler, coordinate,
|
|
/*component*/ 0, comparator, constOffset, varOffset, /*constOffsets*/ 0,
|
|
/*component*/ 0, comparator, constOffset, varOffset, /*constOffsets*/ 0,
|
|
- /*sampleNumber*/ 0, /*isSparse*/ true);
|
|
|
|
- // Write the Residency Code
|
|
|
|
- const auto status =
|
|
|
|
- theBuilder.createCompositeExtract(uintType, sparseGather, {0});
|
|
|
|
- theBuilder.createStore(doExpr(expr->getArg(numArgs - 1)), status);
|
|
|
|
- // Return the results
|
|
|
|
- return theBuilder.createCompositeExtract(retType, sparseGather, {1});
|
|
|
|
|
|
+ /*sampleNumber*/ 0, status);
|
|
}
|
|
}
|
|
|
|
|
|
SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(const Expr *object,
|
|
SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(const Expr *object,
|
|
@@ -2825,35 +2785,52 @@ uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
|
|
// float Location
|
|
// float Location
|
|
// [, int Offset]);
|
|
// [, int Offset]);
|
|
//
|
|
//
|
|
|
|
+ // For Texture2D/Texture2DArray:
|
|
|
|
+ // <Template Type>4 Object.Gather(sampler_state S,
|
|
|
|
+ // float2|3|4 Location,
|
|
|
|
+ // int2 Offset
|
|
|
|
+ // [, uint Status]);
|
|
|
|
+ //
|
|
|
|
+ // For TextureCube/TextureCubeArray:
|
|
// <Template Type>4 Object.Gather(sampler_state S,
|
|
// <Template Type>4 Object.Gather(sampler_state S,
|
|
// float2|3|4 Location
|
|
// float2|3|4 Location
|
|
- // [, int2 Offset]);
|
|
|
|
|
|
+ // [, uint Status]);
|
|
|
|
+ //
|
|
|
|
+ // Other Texture types do not have a Gather method.
|
|
|
|
+
|
|
|
|
+ const auto numArgs = expr->getNumArgs();
|
|
|
|
+ const bool hasStatusArg =
|
|
|
|
+ expr->getArg(numArgs - 1)->getType()->isUnsignedIntegerType();
|
|
|
|
+ const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : 0;
|
|
|
|
+
|
|
|
|
+ // Subtract 1 for status (if it exists), and 2 for sampler_state and location.
|
|
|
|
+ const bool hasOffsetArg = numArgs - hasStatusArg - 2 > 0;
|
|
|
|
|
|
const auto *imageExpr = expr->getImplicitObjectArgument();
|
|
const auto *imageExpr = expr->getImplicitObjectArgument();
|
|
const uint32_t imageType = typeTranslator.translateType(imageExpr->getType());
|
|
const uint32_t imageType = typeTranslator.translateType(imageExpr->getType());
|
|
-
|
|
|
|
const uint32_t image = loadIfGLValue(imageExpr);
|
|
const uint32_t image = loadIfGLValue(imageExpr);
|
|
const uint32_t sampler = doExpr(expr->getArg(0));
|
|
const uint32_t sampler = doExpr(expr->getArg(0));
|
|
const uint32_t coordinate = doExpr(expr->getArg(1));
|
|
const uint32_t coordinate = doExpr(expr->getArg(1));
|
|
- // .Sample()/.Gather() has a third optional paramter for offset.
|
|
|
|
|
|
+ // .Sample()/.Gather() may have a third optional paramter for offset.
|
|
uint32_t constOffset = 0, varOffset = 0;
|
|
uint32_t constOffset = 0, varOffset = 0;
|
|
- handleOptionalOffsetInMethodCall(expr, 2, &constOffset, &varOffset);
|
|
|
|
|
|
+ if(hasOffsetArg)
|
|
|
|
+ handleOffsetInMethodCall(expr, 2, &constOffset, &varOffset);
|
|
|
|
|
|
const auto retType =
|
|
const auto retType =
|
|
typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
|
|
typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
|
|
|
|
|
|
if (isSample) {
|
|
if (isSample) {
|
|
|
|
+ // TODO: Handle sparse cases for this method.
|
|
return theBuilder.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);
|
|
/*constOffsets*/ 0, /*sampleNumber*/ 0);
|
|
} else {
|
|
} else {
|
|
- // TODO: update this function to handle sparse cases.
|
|
|
|
return theBuilder.createImageGather(
|
|
return theBuilder.createImageGather(
|
|
retType, imageType, image, sampler, coordinate,
|
|
retType, 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, /*isSparse*/ false);
|
|
|
|
|
|
+ varOffset, /*constOffsets*/ 0, /*sampleNumber*/ 0, status);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|