Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4328,7 +4328,18 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
const Expr *mipLevel = nullptr, *numLevels = nullptr, *numSamples = nullptr;

assert(isTexture(type) || isRWTexture(type) || isBuffer(type) ||
isRWBuffer(type));
isRWBuffer(type) || isSampledTexture(type));
if (isSampledTexture(type)) {
LowerTypeVisitor lowerTypeVisitor(astContext, spvContext, spirvOptions,
spvBuilder);
const SpirvType *spvType = lowerTypeVisitor.lowerType(
type, SpirvLayoutRule::Void, llvm::None, expr->getExprLoc());
// Get image type based on type, assuming type is a sampledimage type
const auto *sampledType = cast<SampledImageType>(spvType);
const SpirvType *imgType = sampledType->getImageType();
objectInstr = spvBuilder.createUnaryOp(spv::Op::OpImage, imgType,
objectInstr, expr->getExprLoc());
}

// For Texture1D, arguments are either:
// a) width
Expand Down Expand Up @@ -4362,6 +4373,9 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
// a) width, height, elements
// b) MipLevel, width, height, elements, NumLevels

// SampledTexture types follow the same rules above, as
// this method doesn't require a Sampler argument.

// Note: SPIR-V Spec requires return type of OpImageQuerySize(Lod) to be a
// scalar/vector of integers. SPIR-V Spec also requires return type of
// OpImageQueryLevels and OpImageQuerySamples to be scalar integers.
Expand All @@ -4379,6 +4393,7 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {

if ((typeName == "Texture1D" && numArgs > 1) ||
(typeName == "Texture2D" && numArgs > 2) ||
(typeName == "SampledTexture2D" && numArgs > 2) ||
(typeName == "TextureCube" && numArgs > 2) ||
(typeName == "Texture3D" && numArgs > 3) ||
(typeName == "Texture1DArray" && numArgs > 2) ||
Expand Down Expand Up @@ -4417,7 +4432,7 @@ SpirvEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
// Only Texture types use ImageQuerySizeLod.
// TextureMS, RWTexture, Buffers, RWBuffers use ImageQuerySize.
SpirvInstruction *lod = nullptr;
if (isTexture(type) && !numSamples) {
if ((isTexture(type) || isSampledTexture(type)) && !numSamples) {
if (mipLevel) {
// For Texture types when mipLevel argument is present.
lod = doExpr(mipLevel, range);
Expand Down Expand Up @@ -6433,7 +6448,8 @@ SpirvInstruction *
SpirvEmitter::processGetDimensions(const CXXMemberCallExpr *expr) {
const auto objectType = expr->getImplicitObjectArgument()->getType();
if (isTexture(objectType) || isRWTexture(objectType) ||
isBuffer(objectType) || isRWBuffer(objectType)) {
isBuffer(objectType) || isRWBuffer(objectType) ||
isSampledTexture(objectType)) {
return processBufferTextureGetDimensions(expr);
} else if (isByteAddressBuffer(objectType) ||
isRWByteAddressBuffer(objectType) ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// RUN: %dxc -T ps_6_0 -E main -fcgl %s -spirv | FileCheck %s
// RUN: not %dxc -T ps_6_0 -E main -fcgl %s -spirv -DERROR 2>&1 | FileCheck %s --check-prefix=ERROR

// CHECK: OpCapability ImageQuery

vk::SampledTexture2D<float4> t1;

void main() {
uint mipLevel = 1;
uint width, height, numLevels;

// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
// CHECK-NEXT: [[image1:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
// CHECK-NEXT: [[query1:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image1]] %int_0
// CHECK-NEXT: [[query1_0:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 0
// CHECK-NEXT: OpStore %width [[query1_0]]
// CHECK-NEXT: [[query1_1:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 1
// CHECK-NEXT: OpStore %height [[query1_1]]
t1.GetDimensions(width, height);

// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
// CHECK-NEXT: [[image2:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
// CHECK-NEXT: [[mip:%[0-9]+]] = OpLoad %uint %mipLevel
// CHECK-NEXT: [[query2:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image2]] [[mip]]
// CHECK-NEXT: [[query2_0:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 0
// CHECK-NEXT: OpStore %width [[query2_0]]
// CHECK-NEXT: [[query2_1:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 1
// CHECK-NEXT: OpStore %height [[query2_1]]
// CHECK-NEXT: [[query_level_2:%[0-9]+]] = OpImageQueryLevels %uint [[image2]]
// CHECK-NEXT: OpStore %numLevels [[query_level_2]]
t1.GetDimensions(mipLevel, width, height, numLevels);

float f_width, f_height, f_numLevels;
// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
// CHECK-NEXT: [[image1:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
// CHECK-NEXT: [[query1:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image1]] %int_0
// CHECK-NEXT: [[query1_0:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 0
// CHECK-NEXT: [[f_query1_0:%[0-9]+]] = OpConvertUToF %float [[query1_0]]
// CHECK-NEXT: OpStore %f_width [[f_query1_0]]
// CHECK-NEXT: [[query1_1:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 1
// CHECK-NEXT: [[f_query1_1:%[0-9]+]] = OpConvertUToF %float [[query1_1]]
// CHECK-NEXT: OpStore %f_height [[f_query1_1]]
t1.GetDimensions(f_width, f_height);

// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
// CHECK-NEXT: [[image2:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
// CHECK-NEXT: [[mip:%[0-9]+]] = OpLoad %uint %mipLevel
// CHECK-NEXT: [[query2:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image2]] [[mip]]
// CHECK-NEXT: [[query2_0:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 0
// CHECK-NEXT: [[f_query2_0:%[0-9]+]] = OpConvertUToF %float [[query2_0]]
// CHECK-NEXT: OpStore %f_width [[f_query2_0]]
// CHECK-NEXT: [[query2_1:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 1
// CHECK-NEXT: [[f_query2_1:%[0-9]+]] = OpConvertUToF %float [[query2_1]]
// CHECK-NEXT: OpStore %f_height [[f_query2_1]]
// CHECK-NEXT: [[query_level_2:%[0-9]+]] = OpImageQueryLevels %uint [[image2]]
// CHECK-NEXT: [[f_query_level_2:%[0-9]+]] = OpConvertUToF %float [[query_level_2]]
// CHECK-NEXT: OpStore %f_numLevels [[f_query_level_2]]
t1.GetDimensions(mipLevel, f_width, f_height, f_numLevels);

int i_width, i_height, i_numLevels;
// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
// CHECK-NEXT: [[image1:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
// CHECK-NEXT: [[query1:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image1]] %int_0
// CHECK-NEXT: [[query1_0:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 0
// CHECK-NEXT: [[query_0_int:%[0-9]+]] = OpBitcast %int [[query1_0]]
// CHECK-NEXT: OpStore %i_width [[query_0_int]]
// CHECK-NEXT: [[query1_1:%[0-9]+]] = OpCompositeExtract %uint [[query1]] 1
// CHECK-NEXT: [[query_1_int:%[0-9]+]] = OpBitcast %int [[query1_1]]
// CHECK-NEXT: OpStore %i_height [[query_1_int]]
t1.GetDimensions(i_width, i_height);

// CHECK: [[t1_load:%[0-9]+]] = OpLoad %type_sampled_image %t1
// CHECK-NEXT: [[image2:%[0-9]+]] = OpImage %type_2d_image [[t1_load]]
// CHECK-NEXT: [[mip:%[0-9]+]] = OpLoad %uint %mipLevel
// CHECK-NEXT: [[query2:%[0-9]+]] = OpImageQuerySizeLod %v2uint [[image2]] [[mip]]
// CHECK-NEXT: [[query2_0:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 0
// CHECK-NEXT: [[query_0_int:%[0-9]+]] = OpBitcast %int [[query2_0]]
// CHECK-NEXT: OpStore %i_width [[query_0_int]]
// CHECK-NEXT: [[query2_1:%[0-9]+]] = OpCompositeExtract %uint [[query2]] 1
// CHECK-NEXT: [[query_1_int:%[0-9]+]] = OpBitcast %int [[query2_1]]
// CHECK-NEXT: OpStore %i_height [[query_1_int]]
// CHECK-NEXT: [[query_level_2:%[0-9]+]] = OpImageQueryLevels %uint [[image2]]
// CHECK-NEXT: [[query_level_2_int:%[0-9]+]] = OpBitcast %int [[query_level_2]]
// CHECK-NEXT: OpStore %i_numLevels [[query_level_2_int]]
t1.GetDimensions(mipLevel, i_width, i_height, i_numLevels);

#ifdef ERROR
// ERROR: error: Output argument must be an l-value
t1.GetDimensions(mipLevel, 0, height, numLevels);

// ERROR: error: Output argument must be an l-value
t1.GetDimensions(width, 20);
#endif
}
4 changes: 4 additions & 0 deletions utils/hct/gen_intrin_main.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1243,4 +1243,8 @@ namespace VkSampledTexture2DMethods {
$match<0, -1> void<4> [[ro]] Gather(in float<2> x) : tex2d_t_gather;
$match<0, -1> void<4> [[ro]] Gather(in float<2> x, in int<2> o) : tex2d_t_gather_o;
$match<0, -1> void<4> [[]] Gather(in float<2> x, in int<2> o, out uint_only status) : tex2d_t_gather_o_s;
void [[]] GetDimensions(in uint x, out uint_only width, out $type2 height, out $type2 levels) : resinfo_uint;
void [[]] GetDimensions(in uint x, out float_like width, out $type2 height, out $type2 levels) : resinfo;
void [[]] GetDimensions(out uint_only width, out $type1 height) : resinfo_uint_o;
void [[]] GetDimensions(out float_like width, out $type1 height) : resinfo_o;
} namespace