Implement textureNumLayers()
SPIR-V reader TODO Bug: tint:140 Bug: tint:437 Change-Id: Id397f5f07a2f18f365dc9c2d588e619cea8f89dc Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/37844 Reviewed-by: dan sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
0f4638b9e4
commit
c21f1f92a2
|
@ -21,211 +21,220 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i) {
|
|||
/// The emitted name matches the spelling in the WGSL spec.
|
||||
/// including case.
|
||||
switch (i) {
|
||||
case Intrinsic::kNone:
|
||||
return out;
|
||||
case Intrinsic::kAbs:
|
||||
out << "abs";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kAcos:
|
||||
out << "acos";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kAll:
|
||||
out << "all";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kAny:
|
||||
out << "any";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kArrayLength:
|
||||
out << "arrayLength";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kAsin:
|
||||
out << "asin";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kAtan:
|
||||
out << "atan";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kAtan2:
|
||||
out << "atan2";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kCeil:
|
||||
out << "ceil";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kClamp:
|
||||
out << "clamp";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kCos:
|
||||
out << "cos";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kCosh:
|
||||
out << "cosh";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kCountOneBits:
|
||||
out << "countOneBits";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kCross:
|
||||
out << "cross";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDeterminant:
|
||||
out << "determinant";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDistance:
|
||||
out << "distance";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDot:
|
||||
out << "dot";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDpdx:
|
||||
out << "dpdx";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDpdxCoarse:
|
||||
out << "dpdxCoarse";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDpdxFine:
|
||||
out << "dpdxFine";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDpdy:
|
||||
out << "dpdy";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDpdyCoarse:
|
||||
out << "dpdyCoarse";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kDpdyFine:
|
||||
out << "dpdyFine";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kExp:
|
||||
out << "exp";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kExp2:
|
||||
out << "exp2";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kFaceForward:
|
||||
out << "faceForward";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kFloor:
|
||||
out << "floor";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kFma:
|
||||
out << "fma";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kFract:
|
||||
out << "fract";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kFrexp:
|
||||
out << "frexp";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kFwidth:
|
||||
out << "fwidth";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kFwidthCoarse:
|
||||
out << "fwidthCoarse";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kFwidthFine:
|
||||
out << "fwidthFine";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kInverseSqrt:
|
||||
out << "inverseSqrt";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kIsFinite:
|
||||
out << "isFinite";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kIsInf:
|
||||
out << "isInf";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kIsNan:
|
||||
out << "isNan";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kIsNormal:
|
||||
out << "isNormal";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kLdexp:
|
||||
out << "ldexp";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kLength:
|
||||
out << "length";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kLog:
|
||||
out << "log";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kLog2:
|
||||
out << "log2";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kMax:
|
||||
out << "max";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kMin:
|
||||
out << "min";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kMix:
|
||||
out << "mix";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kModf:
|
||||
out << "modf";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kNormalize:
|
||||
out << "normalize";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kPow:
|
||||
out << "pow";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kReflect:
|
||||
out << "reflect";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kReverseBits:
|
||||
out << "reverseBits";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kRound:
|
||||
out << "round";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kSelect:
|
||||
out << "select";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kSign:
|
||||
out << "sign";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kSin:
|
||||
out << "sin";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kSinh:
|
||||
out << "sinh";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kSmoothStep:
|
||||
out << "smoothStep";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kSqrt:
|
||||
out << "sqrt";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kStep:
|
||||
out << "step";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTan:
|
||||
out << "tan";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTanh:
|
||||
out << "tanh";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTextureDimensions:
|
||||
out << "textureDimensions";
|
||||
return out;
|
||||
case Intrinsic::kTextureLoad:
|
||||
out << "textureLoad";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTextureNumLayers:
|
||||
out << "textureNumLayers";
|
||||
return out;
|
||||
case Intrinsic::kTextureSample:
|
||||
out << "textureSample";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTextureSampleBias:
|
||||
out << "textureSampleBias";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTextureSampleCompare:
|
||||
out << "textureSampleCompare";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTextureSampleGrad:
|
||||
out << "textureSampleGrad";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTextureSampleLevel:
|
||||
out << "textureSampleLevel";
|
||||
break;
|
||||
return out;
|
||||
case Intrinsic::kTextureStore:
|
||||
out << "textureStore";
|
||||
return out;
|
||||
case Intrinsic::kTrunc:
|
||||
out << "trunc";
|
||||
break;
|
||||
default:
|
||||
out << "Unknown";
|
||||
break;
|
||||
return out;
|
||||
}
|
||||
out << "Unknown";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -260,7 +269,7 @@ bool IsFloatClassificationIntrinsic(Intrinsic i) {
|
|||
|
||||
bool IsTextureIntrinsic(Intrinsic i) {
|
||||
return i == Intrinsic::kTextureDimensions || i == Intrinsic::kTextureLoad ||
|
||||
i == Intrinsic::kTextureSample ||
|
||||
i == Intrinsic::kTextureNumLayers || i == Intrinsic::kTextureSample ||
|
||||
i == Intrinsic::kTextureSampleLevel ||
|
||||
i == Intrinsic::kTextureSampleBias ||
|
||||
i == Intrinsic::kTextureSampleCompare ||
|
||||
|
@ -268,7 +277,8 @@ bool IsTextureIntrinsic(Intrinsic i) {
|
|||
}
|
||||
|
||||
bool IsImageQueryIntrinsic(Intrinsic i) {
|
||||
return i == ast::Intrinsic::kTextureDimensions;
|
||||
return i == ast::Intrinsic::kTextureDimensions ||
|
||||
i == Intrinsic::kTextureNumLayers;
|
||||
}
|
||||
|
||||
} // namespace intrinsic
|
||||
|
|
|
@ -85,6 +85,7 @@ enum class Intrinsic {
|
|||
kTanh,
|
||||
kTextureDimensions,
|
||||
kTextureLoad,
|
||||
kTextureNumLayers,
|
||||
kTextureSample,
|
||||
kTextureSampleBias,
|
||||
kTextureSampleCompare,
|
||||
|
|
|
@ -541,6 +541,86 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
|
|||
"textureDimensions",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kNumLayers1dArray,
|
||||
"textureNumLayers(t : texture_1d_array<T>) -> i32",
|
||||
TextureKind::kRegular,
|
||||
type::SamplerKind::kSampler,
|
||||
type::TextureDimension::k1dArray,
|
||||
TextureDataType::kF32,
|
||||
"textureNumLayers",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kNumLayers2dArray,
|
||||
"textureNumLayers(t : texture_2d_array<T>) -> i32",
|
||||
TextureKind::kRegular,
|
||||
type::SamplerKind::kSampler,
|
||||
type::TextureDimension::k2dArray,
|
||||
TextureDataType::kF32,
|
||||
"textureNumLayers",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kNumLayersCubeArray,
|
||||
"textureNumLayers(t : texture_cube_array<T>) -> i32",
|
||||
TextureKind::kRegular,
|
||||
type::SamplerKind::kSampler,
|
||||
type::TextureDimension::kCubeArray,
|
||||
TextureDataType::kF32,
|
||||
"textureNumLayers",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kNumLayersMultisampled_2dArray,
|
||||
"textureNumLayers(t : texture_multisampled_2d_array<T>) -> i32",
|
||||
TextureKind::kMultisampled,
|
||||
type::SamplerKind::kSampler,
|
||||
type::TextureDimension::k2dArray,
|
||||
TextureDataType::kF32,
|
||||
"textureNumLayers",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kNumLayersDepth2dArray,
|
||||
"textureNumLayers(t : texture_depth_2d_array) -> i32",
|
||||
TextureKind::kDepth,
|
||||
type::SamplerKind::kSampler,
|
||||
type::TextureDimension::k2dArray,
|
||||
TextureDataType::kF32,
|
||||
"textureNumLayers",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kNumLayersDepthCubeArray,
|
||||
"textureNumLayers(t : texture_depth_cube_array) -> i32",
|
||||
TextureKind::kDepth,
|
||||
type::SamplerKind::kSampler,
|
||||
type::TextureDimension::kCubeArray,
|
||||
TextureDataType::kF32,
|
||||
"textureNumLayers",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kNumLayersStorageWO1dArray,
|
||||
"textureNumLayers(t : texture_storage_1d_array<F>) -> i32",
|
||||
ast::AccessControl::kWriteOnly,
|
||||
ast::type::ImageFormat::kRgba32Float,
|
||||
type::TextureDimension::k1dArray,
|
||||
TextureDataType::kF32,
|
||||
"textureNumLayers",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kNumLayersStorageWO2dArray,
|
||||
"textureNumLayers(t : texture_storage_2d_array<F>) -> i32",
|
||||
ast::AccessControl::kWriteOnly,
|
||||
ast::type::ImageFormat::kRgba32Float,
|
||||
type::TextureDimension::k2dArray,
|
||||
TextureDataType::kF32,
|
||||
"textureNumLayers",
|
||||
[](Builder* b) { return b->ExprList("texture"); },
|
||||
},
|
||||
{
|
||||
ValidTextureOverload::kSample1dF32,
|
||||
"textureSample(t : texture_1d<f32>,\n"
|
||||
|
|
|
@ -69,6 +69,14 @@ enum class ValidTextureOverload {
|
|||
kDimensionsStorageWO2d,
|
||||
kDimensionsStorageWO2dArray,
|
||||
kDimensionsStorageWO3d,
|
||||
kNumLayers1dArray,
|
||||
kNumLayers2dArray,
|
||||
kNumLayersCubeArray,
|
||||
kNumLayersMultisampled_2dArray,
|
||||
kNumLayersDepth2dArray,
|
||||
kNumLayersDepthCubeArray,
|
||||
kNumLayersStorageWO1dArray,
|
||||
kNumLayersStorageWO2dArray,
|
||||
kSample1dF32,
|
||||
kSample1dArrayF32,
|
||||
kSample2dF32,
|
||||
|
|
|
@ -566,6 +566,9 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
|||
param.idx.level = param.count++;
|
||||
}
|
||||
break;
|
||||
case ast::Intrinsic::kTextureNumLayers:
|
||||
param.idx.texture = param.count++;
|
||||
break;
|
||||
case ast::Intrinsic::kTextureLoad:
|
||||
param.idx.texture = param.count++;
|
||||
param.idx.coords = param.count++;
|
||||
|
@ -669,46 +672,54 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
|||
|
||||
// Set the function return type
|
||||
ast::type::Type* return_type = nullptr;
|
||||
if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) {
|
||||
auto* i32 = mod_->create<ast::type::I32>();
|
||||
switch (texture->dim()) {
|
||||
default:
|
||||
set_error(expr->source(), "invalid texture dimensions");
|
||||
break;
|
||||
case ast::type::TextureDimension::k1d:
|
||||
case ast::type::TextureDimension::k1dArray:
|
||||
return_type = i32;
|
||||
break;
|
||||
case ast::type::TextureDimension::k2d:
|
||||
case ast::type::TextureDimension::k2dArray:
|
||||
return_type = mod_->create<ast::type::Vector>(i32, 2);
|
||||
break;
|
||||
case ast::type::TextureDimension::k3d:
|
||||
case ast::type::TextureDimension::kCube:
|
||||
case ast::type::TextureDimension::kCubeArray:
|
||||
return_type = mod_->create<ast::type::Vector>(i32, 3);
|
||||
break;
|
||||
}
|
||||
} else if (ident->intrinsic() == ast::Intrinsic::kTextureStore) {
|
||||
return_type = mod_->create<ast::type::Void>();
|
||||
} else {
|
||||
if (texture->Is<ast::type::DepthTexture>()) {
|
||||
return_type = mod_->create<ast::type::F32>();
|
||||
} else {
|
||||
ast::type::Type* type = nullptr;
|
||||
if (auto* storage = texture->As<ast::type::StorageTexture>()) {
|
||||
type = storage->type();
|
||||
} else if (auto* sampled = texture->As<ast::type::SampledTexture>()) {
|
||||
type = sampled->type();
|
||||
} else if (auto* msampled =
|
||||
texture->As<ast::type::MultisampledTexture>()) {
|
||||
type = msampled->type();
|
||||
} else {
|
||||
set_error(expr->source(),
|
||||
"unknown texture type for texture sampling");
|
||||
return false;
|
||||
switch (ident->intrinsic()) {
|
||||
case ast::Intrinsic::kTextureDimensions: {
|
||||
auto* i32 = mod_->create<ast::type::I32>();
|
||||
switch (texture->dim()) {
|
||||
default:
|
||||
set_error(expr->source(), "invalid texture dimensions");
|
||||
break;
|
||||
case ast::type::TextureDimension::k1d:
|
||||
case ast::type::TextureDimension::k1dArray:
|
||||
return_type = i32;
|
||||
break;
|
||||
case ast::type::TextureDimension::k2d:
|
||||
case ast::type::TextureDimension::k2dArray:
|
||||
return_type = mod_->create<ast::type::Vector>(i32, 2);
|
||||
break;
|
||||
case ast::type::TextureDimension::k3d:
|
||||
case ast::type::TextureDimension::kCube:
|
||||
case ast::type::TextureDimension::kCubeArray:
|
||||
return_type = mod_->create<ast::type::Vector>(i32, 3);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureNumLayers:
|
||||
return_type = mod_->create<ast::type::I32>();
|
||||
break;
|
||||
case ast::Intrinsic::kTextureStore:
|
||||
return_type = mod_->create<ast::type::Void>();
|
||||
break;
|
||||
default: {
|
||||
if (texture->Is<ast::type::DepthTexture>()) {
|
||||
return_type = mod_->create<ast::type::F32>();
|
||||
} else {
|
||||
ast::type::Type* type = nullptr;
|
||||
if (auto* storage = texture->As<ast::type::StorageTexture>()) {
|
||||
type = storage->type();
|
||||
} else if (auto* sampled = texture->As<ast::type::SampledTexture>()) {
|
||||
type = sampled->type();
|
||||
} else if (auto* msampled =
|
||||
texture->As<ast::type::MultisampledTexture>()) {
|
||||
type = msampled->type();
|
||||
} else {
|
||||
set_error(expr->source(),
|
||||
"unknown texture type for texture sampling");
|
||||
return false;
|
||||
}
|
||||
return_type = mod_->create<ast::type::Vector>(type, 4);
|
||||
}
|
||||
return_type = mod_->create<ast::type::Vector>(type, 4);
|
||||
}
|
||||
}
|
||||
expr->func()->set_result_type(return_type);
|
||||
|
@ -1021,6 +1032,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
|
|||
ident->set_intrinsic(ast::Intrinsic::kTanh);
|
||||
} else if (name == "textureDimensions") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureDimensions);
|
||||
} else if (name == "textureNumLayers") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureNumLayers);
|
||||
} else if (name == "textureLoad") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureLoad);
|
||||
} else if (name == "textureStore") {
|
||||
|
|
|
@ -1764,6 +1764,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
IntrinsicData{"tanh", ast::Intrinsic::kTanh},
|
||||
IntrinsicData{"textureDimensions", ast::Intrinsic::kTextureDimensions},
|
||||
IntrinsicData{"textureLoad", ast::Intrinsic::kTextureLoad},
|
||||
IntrinsicData{"textureNumLayers", ast::Intrinsic::kTextureNumLayers},
|
||||
IntrinsicData{"textureSample", ast::Intrinsic::kTextureSample},
|
||||
IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias},
|
||||
IntrinsicData{"textureSampleCompare",
|
||||
|
@ -2928,6 +2929,15 @@ const char* expected_texture_overload(
|
|||
case ValidTextureOverload::kDimensionsStorageWO2dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageWO3d:
|
||||
return R"(textureDimensions(texture))";
|
||||
case ValidTextureOverload::kNumLayers1dArray:
|
||||
case ValidTextureOverload::kNumLayers2dArray:
|
||||
case ValidTextureOverload::kNumLayersCubeArray:
|
||||
case ValidTextureOverload::kNumLayersMultisampled_2dArray:
|
||||
case ValidTextureOverload::kNumLayersDepth2dArray:
|
||||
case ValidTextureOverload::kNumLayersDepthCubeArray:
|
||||
case ValidTextureOverload::kNumLayersStorageWO1dArray:
|
||||
case ValidTextureOverload::kNumLayersStorageWO2dArray:
|
||||
return R"(textureNumLayers(texture))";
|
||||
case ValidTextureOverload::kDimensions2dLevel:
|
||||
case ValidTextureOverload::kDimensions2dArrayLevel:
|
||||
case ValidTextureOverload::kDimensions3dLevel:
|
||||
|
@ -3181,6 +3191,8 @@ TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
|
|||
ty.vec3<i32>()->type_name());
|
||||
break;
|
||||
}
|
||||
} else if (std::string(param.function) == "textureNumLayers") {
|
||||
EXPECT_EQ(call->result_type(), ty.i32);
|
||||
} else if (std::string(param.function) == "textureStore") {
|
||||
EXPECT_EQ(call->result_type(), ty.void_);
|
||||
} else {
|
||||
|
|
|
@ -695,49 +695,99 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
|
|||
auto* texture_type =
|
||||
texture->result_type()->UnwrapAll()->As<ast::type::Texture>();
|
||||
|
||||
if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) {
|
||||
// Declare a variable to hold the texture dimensions
|
||||
auto dims = generate_name(kTempNamePrefix);
|
||||
EmitType(pre, expr->result_type(), "");
|
||||
pre << " " << dims << ";" << std::endl;
|
||||
switch (ident->intrinsic()) {
|
||||
case ast::Intrinsic::kTextureDimensions:
|
||||
case ast::Intrinsic::kTextureNumLayers: {
|
||||
// Declare a variable to hold the queried texture info
|
||||
auto dims = generate_name(kTempNamePrefix);
|
||||
|
||||
// Now call GetDimensions() on the texture object, populating the dims
|
||||
// variable.
|
||||
std::stringstream tex_out;
|
||||
if (!EmitExpression(pre, tex_out, texture)) {
|
||||
return false;
|
||||
}
|
||||
pre << tex_out.str() << ".GetDimensions(";
|
||||
if (pidx.level != kNotUsed) {
|
||||
pre << pidx.level << ", ";
|
||||
}
|
||||
switch (texture_type->dim()) {
|
||||
case ast::type::TextureDimension::kNone:
|
||||
error_ = "texture dimension is kNone";
|
||||
std::stringstream texture_name;
|
||||
if (!EmitExpression(pre, texture_name, texture)) {
|
||||
return false;
|
||||
case ast::type::TextureDimension::k1d:
|
||||
case ast::type::TextureDimension::k1dArray:
|
||||
pre << dims << ");";
|
||||
break;
|
||||
case ast::type::TextureDimension::k2d:
|
||||
case ast::type::TextureDimension::k2dArray:
|
||||
pre << dims << "[0], " << dims << "[1]);";
|
||||
break;
|
||||
case ast::type::TextureDimension::k3d:
|
||||
pre << dims << "[0], " << dims << "[1], " << dims << "[2]);";
|
||||
break;
|
||||
case ast::type::TextureDimension::kCube:
|
||||
case ast::type::TextureDimension::kCubeArray:
|
||||
// width == height == depth for cubes
|
||||
// See https://github.com/gpuweb/gpuweb/issues/1345
|
||||
pre << dims << "[0], " << dims << "[1]);\n";
|
||||
pre << dims << "[2] = " << dims << "[1];"; // dims[2] = dims[1]
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The result of the textureDimensions() call is now the temporary variable.
|
||||
out << dims;
|
||||
return true;
|
||||
auto get_dimensions = [&](std::initializer_list<const char*>&& suffixes) {
|
||||
pre << texture_name.str() << ".GetDimensions(";
|
||||
if (pidx.level != kNotUsed) {
|
||||
pre << pidx.level << ", ";
|
||||
}
|
||||
bool first = true;
|
||||
for (auto* suffix : suffixes) {
|
||||
if (!first) {
|
||||
pre << ", ";
|
||||
}
|
||||
first = false;
|
||||
pre << dims << suffix;
|
||||
}
|
||||
pre << ");";
|
||||
};
|
||||
|
||||
const char* dims_swizzle = "";
|
||||
const char* num_els_swizzle = "";
|
||||
|
||||
std::stringstream ss;
|
||||
switch (texture_type->dim()) {
|
||||
case ast::type::TextureDimension::kNone:
|
||||
error_ = "texture dimension is kNone";
|
||||
return false;
|
||||
case ast::type::TextureDimension::k1d:
|
||||
pre << "int " << dims << ";\n";
|
||||
get_dimensions({""});
|
||||
break;
|
||||
case ast::type::TextureDimension::k1dArray:
|
||||
pre << "int2 " << dims << ";\n";
|
||||
get_dimensions({".x", ".y"});
|
||||
dims_swizzle = ".x";
|
||||
num_els_swizzle = ".y";
|
||||
break;
|
||||
case ast::type::TextureDimension::k2d:
|
||||
pre << "int2 " << dims << ";\n";
|
||||
get_dimensions({".x", ".y"});
|
||||
break;
|
||||
case ast::type::TextureDimension::k2dArray:
|
||||
pre << "int3 " << dims << ";\n";
|
||||
get_dimensions({".x", ".y", ".z"});
|
||||
dims_swizzle = ".xy";
|
||||
num_els_swizzle = ".z";
|
||||
break;
|
||||
case ast::type::TextureDimension::k3d:
|
||||
pre << "int3 " << dims << ";\n";
|
||||
get_dimensions({".x", ".y", ".z"});
|
||||
break;
|
||||
case ast::type::TextureDimension::kCube:
|
||||
// width == height == depth for cubes
|
||||
// See https://github.com/gpuweb/gpuweb/issues/1345
|
||||
pre << "int2 " << dims << ";\n";
|
||||
get_dimensions({".x", ".y"});
|
||||
dims_swizzle = ".xyy"; // [width, height, height]
|
||||
break;
|
||||
case ast::type::TextureDimension::kCubeArray:
|
||||
// width == height == depth for cubes
|
||||
// See https://github.com/gpuweb/gpuweb/issues/1345
|
||||
pre << "int3 " << dims << ";\n";
|
||||
get_dimensions({".x", ".y", ".z"});
|
||||
dims_swizzle = ".xyy"; // [width, height, height]
|
||||
num_els_swizzle = ".z";
|
||||
break;
|
||||
}
|
||||
|
||||
// The result of the textureDimensions() call is now in temporary
|
||||
// variable. This may be packed with other data, so the final expression
|
||||
// may require a swizzle.
|
||||
switch (ident->intrinsic()) {
|
||||
case ast::Intrinsic::kTextureDimensions:
|
||||
out << dims << dims_swizzle;
|
||||
return true;
|
||||
case ast::Intrinsic::kTextureNumLayers:
|
||||
out << dims << num_els_swizzle;
|
||||
return true;
|
||||
default:
|
||||
error_ = "Unhandled intrinsic";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!EmitExpression(pre, out, texture))
|
||||
|
|
|
@ -41,75 +41,121 @@ ExpectedResult expected_texture_overload(
|
|||
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
|
||||
switch (overload) {
|
||||
case ValidTextureOverload::kDimensions1d:
|
||||
case ValidTextureOverload::kDimensions1dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageRO1d:
|
||||
case ValidTextureOverload::kDimensionsStorageRO1dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageWO1d:
|
||||
case ValidTextureOverload::kDimensionsStorageWO1dArray:
|
||||
return {
|
||||
"int _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(_tint_tmp);",
|
||||
"_tint_tmp",
|
||||
};
|
||||
case ValidTextureOverload::kDimensions2d:
|
||||
case ValidTextureOverload::kDimensions2dArray:
|
||||
case ValidTextureOverload::kDimensionsMultisampled_2d:
|
||||
case ValidTextureOverload::kDimensionsMultisampled_2dArray:
|
||||
case ValidTextureOverload::kDimensionsDepth2d:
|
||||
case ValidTextureOverload::kDimensionsDepth2dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageRO2d:
|
||||
case ValidTextureOverload::kDimensionsStorageRO2dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageWO2d:
|
||||
case ValidTextureOverload::kDimensionsStorageWO2dArray:
|
||||
case ValidTextureOverload::kDimensions1dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageRO1dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageWO1dArray:
|
||||
return {
|
||||
"int2 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(_tint_tmp[0], _tint_tmp[1]);",
|
||||
"texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y);",
|
||||
"_tint_tmp.x",
|
||||
};
|
||||
case ValidTextureOverload::kDimensions2d:
|
||||
case ValidTextureOverload::kDimensionsMultisampled_2d:
|
||||
case ValidTextureOverload::kDimensionsDepth2d:
|
||||
case ValidTextureOverload::kDimensionsStorageRO2d:
|
||||
case ValidTextureOverload::kDimensionsStorageWO2d:
|
||||
return {
|
||||
"int2 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y);",
|
||||
"_tint_tmp",
|
||||
};
|
||||
case ValidTextureOverload::kDimensions2dArray:
|
||||
case ValidTextureOverload::kDimensionsMultisampled_2dArray:
|
||||
case ValidTextureOverload::kDimensionsDepth2dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageRO2dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageWO2dArray:
|
||||
return {
|
||||
"int3 _tint_tmp;\n"
|
||||
"texture_tint_0."
|
||||
"GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
|
||||
"_tint_tmp.xy",
|
||||
};
|
||||
case ValidTextureOverload::kDimensions3d:
|
||||
case ValidTextureOverload::kDimensionsStorageRO3d:
|
||||
case ValidTextureOverload::kDimensionsStorageWO3d:
|
||||
return {
|
||||
"int3 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(_tint_tmp[0], _tint_tmp[1], "
|
||||
"_tint_tmp[2]);",
|
||||
"texture_tint_0."
|
||||
"GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
|
||||
"_tint_tmp",
|
||||
};
|
||||
case ValidTextureOverload::kDimensionsCube:
|
||||
case ValidTextureOverload::kDimensionsCubeArray:
|
||||
case ValidTextureOverload::kDimensionsDepthCube:
|
||||
return {
|
||||
"int2 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y);",
|
||||
"_tint_tmp.xyy",
|
||||
};
|
||||
case ValidTextureOverload::kDimensionsCubeArray:
|
||||
case ValidTextureOverload::kDimensionsDepthCubeArray:
|
||||
return {
|
||||
"int3 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(_tint_tmp[0], _tint_tmp[1]);\n"
|
||||
"_tint_tmp[2] = _tint_tmp[1];",
|
||||
"_tint_tmp",
|
||||
"texture_tint_0."
|
||||
"GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
|
||||
"_tint_tmp.xyy",
|
||||
};
|
||||
case ValidTextureOverload::kDimensions2dLevel:
|
||||
case ValidTextureOverload::kDimensions2dArrayLevel:
|
||||
case ValidTextureOverload::kDimensionsDepth2dLevel:
|
||||
case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
|
||||
return {
|
||||
"int2 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(1, _tint_tmp[0], _tint_tmp[1]);",
|
||||
"texture_tint_0.GetDimensions(1, _tint_tmp.x, _tint_tmp.y);",
|
||||
"_tint_tmp",
|
||||
};
|
||||
case ValidTextureOverload::kDimensions2dArrayLevel:
|
||||
case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
|
||||
return {
|
||||
"int3 _tint_tmp;\n"
|
||||
"texture_tint_0."
|
||||
"GetDimensions(1, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
|
||||
"_tint_tmp.xy",
|
||||
};
|
||||
case ValidTextureOverload::kDimensions3dLevel:
|
||||
return {
|
||||
"int3 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(1, _tint_tmp[0], _tint_tmp[1], "
|
||||
"_tint_tmp[2]);",
|
||||
"texture_tint_0."
|
||||
"GetDimensions(1, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
|
||||
"_tint_tmp",
|
||||
};
|
||||
case ValidTextureOverload::kDimensionsCubeLevel:
|
||||
case ValidTextureOverload::kDimensionsCubeArrayLevel:
|
||||
case ValidTextureOverload::kDimensionsDepthCubeLevel:
|
||||
return {
|
||||
"int2 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(1, _tint_tmp.x, _tint_tmp.y);",
|
||||
"_tint_tmp.xyy",
|
||||
};
|
||||
case ValidTextureOverload::kDimensionsCubeArrayLevel:
|
||||
case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
|
||||
return {
|
||||
"int3 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(1, _tint_tmp[0], _tint_tmp[1]);\n"
|
||||
"_tint_tmp[2] = _tint_tmp[1];",
|
||||
"_tint_tmp",
|
||||
"texture_tint_0."
|
||||
"GetDimensions(1, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
|
||||
"_tint_tmp.xyy",
|
||||
};
|
||||
case ValidTextureOverload::kNumLayers1dArray:
|
||||
case ValidTextureOverload::kNumLayersStorageWO1dArray:
|
||||
return {
|
||||
"int2 _tint_tmp;\n"
|
||||
"texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y);",
|
||||
"_tint_tmp.y",
|
||||
};
|
||||
case ValidTextureOverload::kNumLayers2dArray:
|
||||
case ValidTextureOverload::kNumLayersMultisampled_2dArray:
|
||||
case ValidTextureOverload::kNumLayersDepth2dArray:
|
||||
case ValidTextureOverload::kNumLayersCubeArray:
|
||||
case ValidTextureOverload::kNumLayersDepthCubeArray:
|
||||
case ValidTextureOverload::kNumLayersStorageWO2dArray:
|
||||
return {
|
||||
"int3 _tint_tmp;\n"
|
||||
"texture_tint_0."
|
||||
"GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
|
||||
"_tint_tmp.z",
|
||||
};
|
||||
case ValidTextureOverload::kSample1dF32:
|
||||
return R"(texture_tint_0.Sample(sampler_tint_0, 1.0f))";
|
||||
|
|
|
@ -616,57 +616,71 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
|||
->UnwrapAll()
|
||||
->As<ast::type::Texture>();
|
||||
|
||||
if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) {
|
||||
std::vector<const char*> dims;
|
||||
switch (texture_type->dim()) {
|
||||
case ast::type::TextureDimension::kNone:
|
||||
error_ = "texture dimension is kNone";
|
||||
return false;
|
||||
case ast::type::TextureDimension::k1d:
|
||||
case ast::type::TextureDimension::k1dArray:
|
||||
dims = {"width"};
|
||||
break;
|
||||
case ast::type::TextureDimension::k2d:
|
||||
case ast::type::TextureDimension::k2dArray:
|
||||
dims = {"width", "height"};
|
||||
break;
|
||||
case ast::type::TextureDimension::k3d:
|
||||
dims = {"width", "height", "depth"};
|
||||
break;
|
||||
case ast::type::TextureDimension::kCube:
|
||||
case ast::type::TextureDimension::kCubeArray:
|
||||
// width == height == depth for cubes
|
||||
// See https://github.com/gpuweb/gpuweb/issues/1345
|
||||
dims = {"width", "height", "height"};
|
||||
break;
|
||||
}
|
||||
switch (ident->intrinsic()) {
|
||||
case ast::Intrinsic::kTextureDimensions: {
|
||||
std::vector<const char*> dims;
|
||||
switch (texture_type->dim()) {
|
||||
case ast::type::TextureDimension::kNone:
|
||||
error_ = "texture dimension is kNone";
|
||||
return false;
|
||||
case ast::type::TextureDimension::k1d:
|
||||
case ast::type::TextureDimension::k1dArray:
|
||||
dims = {"width"};
|
||||
break;
|
||||
case ast::type::TextureDimension::k2d:
|
||||
case ast::type::TextureDimension::k2dArray:
|
||||
dims = {"width", "height"};
|
||||
break;
|
||||
case ast::type::TextureDimension::k3d:
|
||||
dims = {"width", "height", "depth"};
|
||||
break;
|
||||
case ast::type::TextureDimension::kCube:
|
||||
case ast::type::TextureDimension::kCubeArray:
|
||||
// width == height == depth for cubes
|
||||
// See https://github.com/gpuweb/gpuweb/issues/1345
|
||||
dims = {"width", "height", "height"};
|
||||
break;
|
||||
}
|
||||
|
||||
auto get_dim = [&](const char* name) {
|
||||
auto get_dim = [&](const char* name) {
|
||||
if (!EmitExpression(params[pidx.texture])) {
|
||||
return false;
|
||||
}
|
||||
out_ << ".get_" << name << "(";
|
||||
if (pidx.level != kNotUsed) {
|
||||
out_ << pidx.level;
|
||||
}
|
||||
out_ << ")";
|
||||
return true;
|
||||
};
|
||||
|
||||
if (dims.size() == 1) {
|
||||
out_ << "int(";
|
||||
get_dim(dims[0]);
|
||||
out_ << ")";
|
||||
} else {
|
||||
EmitType(expr->result_type(), "");
|
||||
out_ << "(";
|
||||
for (size_t i = 0; i < dims.size(); i++) {
|
||||
if (i > 0) {
|
||||
out_ << ", ";
|
||||
}
|
||||
get_dim(dims[i]);
|
||||
}
|
||||
out_ << ")";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case ast::Intrinsic::kTextureNumLayers: {
|
||||
out_ << "int(";
|
||||
if (!EmitExpression(params[pidx.texture])) {
|
||||
return false;
|
||||
}
|
||||
out_ << ".get_" << name << "(";
|
||||
if (pidx.level != kNotUsed) {
|
||||
out_ << pidx.level;
|
||||
}
|
||||
out_ << ")";
|
||||
out_ << ".get_array_size())";
|
||||
return true;
|
||||
};
|
||||
|
||||
if (dims.size() == 1) {
|
||||
get_dim(dims[0]);
|
||||
} else {
|
||||
EmitType(expr->result_type(), "");
|
||||
out_ << "(";
|
||||
for (size_t i = 0; i < dims.size(); i++) {
|
||||
if (i > 0) {
|
||||
out_ << ", ";
|
||||
}
|
||||
get_dim(dims[i]);
|
||||
}
|
||||
out_ << ")";
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!EmitExpression(params[pidx.texture]))
|
||||
|
|
|
@ -38,7 +38,7 @@ std::string expected_texture_overload(
|
|||
case ValidTextureOverload::kDimensionsStorageRO1dArray:
|
||||
case ValidTextureOverload::kDimensionsStorageWO1d:
|
||||
case ValidTextureOverload::kDimensionsStorageWO1dArray:
|
||||
return R"(texture_tint_0.get_width())";
|
||||
return R"(int(texture_tint_0.get_width()))";
|
||||
case ValidTextureOverload::kDimensions2d:
|
||||
case ValidTextureOverload::kDimensions2dArray:
|
||||
case ValidTextureOverload::kDimensionsMultisampled_2d:
|
||||
|
@ -71,6 +71,15 @@ std::string expected_texture_overload(
|
|||
case ValidTextureOverload::kDimensionsDepthCubeLevel:
|
||||
case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
|
||||
return R"(int3(texture_tint_0.get_width(1), texture_tint_0.get_height(1), texture_tint_0.get_height(1)))";
|
||||
case ValidTextureOverload::kNumLayers1dArray:
|
||||
case ValidTextureOverload::kNumLayers2dArray:
|
||||
case ValidTextureOverload::kNumLayersCubeArray:
|
||||
case ValidTextureOverload::kNumLayersMultisampled_2dArray:
|
||||
case ValidTextureOverload::kNumLayersDepth2dArray:
|
||||
case ValidTextureOverload::kNumLayersDepthCubeArray:
|
||||
case ValidTextureOverload::kNumLayersStorageWO1dArray:
|
||||
case ValidTextureOverload::kNumLayersStorageWO2dArray:
|
||||
return R"(int(texture_tint_0.get_array_size()))";
|
||||
case ValidTextureOverload::kSample1dF32:
|
||||
return R"(texture_tint_0.sample(sampler_tint_0, 1.0f))";
|
||||
case ValidTextureOverload::kSample1dArrayF32:
|
||||
|
|
|
@ -2073,6 +2073,49 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
|||
return true;
|
||||
};
|
||||
|
||||
// Appends a result type and id to `spirv_params`, by first swizzling the
|
||||
// result of the op with `swizzle`.
|
||||
auto append_result_type_and_id_to_spirv_params_swizzled =
|
||||
[&](uint32_t spirv_result_width, std::vector<uint32_t> swizzle) {
|
||||
if (swizzle.empty()) {
|
||||
append_result_type_and_id_to_spirv_params();
|
||||
} else {
|
||||
// Assign post_emission to swizzle the result of the call to
|
||||
// OpImageQuerySize[Lod].
|
||||
auto* element_type = ElementTypeOf(call->result_type());
|
||||
auto spirv_result = result_op();
|
||||
auto* spirv_result_type =
|
||||
mod_->create<ast::type::Vector>(element_type, spirv_result_width);
|
||||
if (swizzle.size() > 1) {
|
||||
post_emission = [=] {
|
||||
OperandList operands{
|
||||
result_type,
|
||||
result_id,
|
||||
spirv_result,
|
||||
spirv_result,
|
||||
};
|
||||
for (auto idx : swizzle) {
|
||||
operands.emplace_back(Operand::Int(idx));
|
||||
}
|
||||
return push_function_inst(spv::Op::OpVectorShuffle, operands);
|
||||
};
|
||||
} else {
|
||||
post_emission = [=] {
|
||||
return push_function_inst(spv::Op::OpCompositeExtract,
|
||||
{result_type, result_id, spirv_result,
|
||||
Operand::Int(swizzle[0])});
|
||||
};
|
||||
}
|
||||
auto spirv_result_type_id = GenerateTypeIfNeeded(spirv_result_type);
|
||||
if (spirv_result_type_id == 0) {
|
||||
return false;
|
||||
}
|
||||
spirv_params.emplace_back(Operand::Int(spirv_result_type_id));
|
||||
spirv_params.emplace_back(spirv_result);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
auto append_coords_to_spirv_params = [&]() -> bool {
|
||||
if (pidx.array_index != kNotUsed) {
|
||||
// Array index needs to be appended to the coordinates.
|
||||
|
@ -2147,41 +2190,9 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
|||
break;
|
||||
}
|
||||
|
||||
if (swizzle.empty()) {
|
||||
append_result_type_and_id_to_spirv_params();
|
||||
} else {
|
||||
// Assign post_emission to swizzle the result of the call to
|
||||
// OpImageQuerySize[Lod].
|
||||
auto* element_type = ElementTypeOf(call->result_type());
|
||||
auto spirv_result = result_op();
|
||||
auto* spirv_result_type =
|
||||
mod_->create<ast::type::Vector>(element_type, spirv_dims);
|
||||
if (swizzle.size() > 1) {
|
||||
post_emission = [=] {
|
||||
OperandList operands{
|
||||
result_type,
|
||||
result_id,
|
||||
spirv_result,
|
||||
spirv_result,
|
||||
};
|
||||
for (auto idx : swizzle) {
|
||||
operands.emplace_back(Operand::Int(idx));
|
||||
}
|
||||
return push_function_inst(spv::Op::OpVectorShuffle, operands);
|
||||
};
|
||||
} else {
|
||||
post_emission = [=] {
|
||||
return push_function_inst(spv::Op::OpCompositeExtract,
|
||||
{result_type, result_id, spirv_result,
|
||||
Operand::Int(swizzle[0])});
|
||||
};
|
||||
}
|
||||
auto spirv_result_type_id = GenerateTypeIfNeeded(spirv_result_type);
|
||||
if (spirv_result_type_id == 0) {
|
||||
return false;
|
||||
}
|
||||
spirv_params.emplace_back(Operand::Int(spirv_result_type_id));
|
||||
spirv_params.emplace_back(spirv_result);
|
||||
if (!append_result_type_and_id_to_spirv_params_swizzled(spirv_dims,
|
||||
swizzle)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
spirv_params.emplace_back(gen_param(pidx.texture));
|
||||
|
@ -2199,6 +2210,41 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureNumLayers: {
|
||||
uint32_t spirv_dims = 0;
|
||||
switch (texture_type->dim()) {
|
||||
default:
|
||||
error_ = "texture is not arrayed";
|
||||
return false;
|
||||
case ast::type::TextureDimension::k1dArray:
|
||||
spirv_dims = 2;
|
||||
break;
|
||||
case ast::type::TextureDimension::k2dArray:
|
||||
case ast::type::TextureDimension::kCubeArray:
|
||||
spirv_dims = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// OpImageQuerySize[Lod] packs the array count as the last element of the
|
||||
// returned vector. Extract this.
|
||||
if (!append_result_type_and_id_to_spirv_params_swizzled(
|
||||
spirv_dims, {spirv_dims - 1})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
spirv_params.emplace_back(gen_param(pidx.texture));
|
||||
|
||||
if (texture_type->Is<ast::type::MultisampledTexture>() ||
|
||||
texture_type->Is<ast::type::StorageTexture>()) {
|
||||
op = spv::Op::OpImageQuerySize;
|
||||
} else {
|
||||
ast::SintLiteral i32_0(Source{}, mod_->create<ast::type::I32>(), 0);
|
||||
op = spv::Op::OpImageQuerySizeLod;
|
||||
spirv_params.emplace_back(
|
||||
Operand::Int(GenerateLiteralIfNeeded(nullptr, &i32_0)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureLoad: {
|
||||
op = texture_type->Is<ast::type::StorageTexture>()
|
||||
? spv::Op::OpImageRead
|
||||
|
|
|
@ -739,6 +739,176 @@ OpCapability ImageQuery
|
|||
)",
|
||||
R"(
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
|
||||
case ValidTextureOverload::kNumLayers1dArray:
|
||||
return {R"(
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeImage %4 1D 0 1 0 1 Unknown
|
||||
%2 = OpTypePointer UniformConstant %3
|
||||
%1 = OpVariable %2 UniformConstant
|
||||
%7 = OpTypeSampler
|
||||
%6 = OpTypePointer UniformConstant %7
|
||||
%5 = OpVariable %6 UniformConstant
|
||||
%9 = OpTypeInt 32 1
|
||||
%11 = OpTypeVector %9 2
|
||||
%13 = OpConstant %9 0
|
||||
)",
|
||||
R"(
|
||||
%12 = OpLoad %3 %1
|
||||
%10 = OpImageQuerySizeLod %11 %12 %13
|
||||
%8 = OpCompositeExtract %9 %10 1
|
||||
)",
|
||||
R"(
|
||||
OpCapability Sampled1D
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
case ValidTextureOverload::kNumLayers2dArray:
|
||||
return {R"(
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
|
||||
%2 = OpTypePointer UniformConstant %3
|
||||
%1 = OpVariable %2 UniformConstant
|
||||
%7 = OpTypeSampler
|
||||
%6 = OpTypePointer UniformConstant %7
|
||||
%5 = OpVariable %6 UniformConstant
|
||||
%9 = OpTypeInt 32 1
|
||||
%11 = OpTypeVector %9 3
|
||||
%13 = OpConstant %9 0
|
||||
)",
|
||||
R"(
|
||||
%12 = OpLoad %3 %1
|
||||
%10 = OpImageQuerySizeLod %11 %12 %13
|
||||
%8 = OpCompositeExtract %9 %10 2
|
||||
)",
|
||||
R"(
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
case ValidTextureOverload::kNumLayersCubeArray:
|
||||
return {R"(
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeImage %4 Cube 0 1 0 1 Unknown
|
||||
%2 = OpTypePointer UniformConstant %3
|
||||
%1 = OpVariable %2 UniformConstant
|
||||
%7 = OpTypeSampler
|
||||
%6 = OpTypePointer UniformConstant %7
|
||||
%5 = OpVariable %6 UniformConstant
|
||||
%9 = OpTypeInt 32 1
|
||||
%11 = OpTypeVector %9 3
|
||||
%13 = OpConstant %9 0
|
||||
)",
|
||||
R"(
|
||||
%12 = OpLoad %3 %1
|
||||
%10 = OpImageQuerySizeLod %11 %12 %13
|
||||
%8 = OpCompositeExtract %9 %10 2
|
||||
)",
|
||||
R"(
|
||||
OpCapability SampledCubeArray
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
case ValidTextureOverload::kNumLayersMultisampled_2dArray:
|
||||
return {R"(
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeImage %4 2D 0 1 1 1 Unknown
|
||||
%2 = OpTypePointer UniformConstant %3
|
||||
%1 = OpVariable %2 UniformConstant
|
||||
%7 = OpTypeSampler
|
||||
%6 = OpTypePointer UniformConstant %7
|
||||
%5 = OpVariable %6 UniformConstant
|
||||
%9 = OpTypeInt 32 1
|
||||
%11 = OpTypeVector %9 3
|
||||
)",
|
||||
R"(
|
||||
%12 = OpLoad %3 %1
|
||||
%10 = OpImageQuerySize %11 %12
|
||||
%8 = OpCompositeExtract %9 %10 2
|
||||
)",
|
||||
R"(
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
case ValidTextureOverload::kNumLayersDepth2dArray:
|
||||
return {R"(
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeImage %4 2D 1 1 0 1 Unknown
|
||||
%2 = OpTypePointer UniformConstant %3
|
||||
%1 = OpVariable %2 UniformConstant
|
||||
%7 = OpTypeSampler
|
||||
%6 = OpTypePointer UniformConstant %7
|
||||
%5 = OpVariable %6 UniformConstant
|
||||
%9 = OpTypeInt 32 1
|
||||
%11 = OpTypeVector %9 3
|
||||
%13 = OpConstant %9 0
|
||||
)",
|
||||
R"(
|
||||
%12 = OpLoad %3 %1
|
||||
%10 = OpImageQuerySizeLod %11 %12 %13
|
||||
%8 = OpCompositeExtract %9 %10 2
|
||||
)",
|
||||
R"(
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
case ValidTextureOverload::kNumLayersDepthCubeArray:
|
||||
return {R"(
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeImage %4 Cube 1 1 0 1 Unknown
|
||||
%2 = OpTypePointer UniformConstant %3
|
||||
%1 = OpVariable %2 UniformConstant
|
||||
%7 = OpTypeSampler
|
||||
%6 = OpTypePointer UniformConstant %7
|
||||
%5 = OpVariable %6 UniformConstant
|
||||
%9 = OpTypeInt 32 1
|
||||
%11 = OpTypeVector %9 3
|
||||
%13 = OpConstant %9 0
|
||||
)",
|
||||
R"(
|
||||
%12 = OpLoad %3 %1
|
||||
%10 = OpImageQuerySizeLod %11 %12 %13
|
||||
%8 = OpCompositeExtract %9 %10 2
|
||||
)",
|
||||
R"(
|
||||
OpCapability SampledCubeArray
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
case ValidTextureOverload::kNumLayersStorageWO1dArray:
|
||||
return {R"(
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeImage %4 1D 0 1 0 2 Rgba32f
|
||||
%2 = OpTypePointer UniformConstant %3
|
||||
%1 = OpVariable %2 UniformConstant
|
||||
%7 = OpTypeSampler
|
||||
%6 = OpTypePointer UniformConstant %7
|
||||
%5 = OpVariable %6 UniformConstant
|
||||
%9 = OpTypeInt 32 1
|
||||
%11 = OpTypeVector %9 2
|
||||
)",
|
||||
R"(
|
||||
%12 = OpLoad %3 %1
|
||||
%10 = OpImageQuerySize %11 %12
|
||||
%8 = OpCompositeExtract %9 %10 1
|
||||
)",
|
||||
R"(
|
||||
OpCapability Image1D
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
case ValidTextureOverload::kNumLayersStorageWO2dArray:
|
||||
return {R"(
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeImage %4 2D 0 1 0 2 Rgba32f
|
||||
%2 = OpTypePointer UniformConstant %3
|
||||
%1 = OpVariable %2 UniformConstant
|
||||
%7 = OpTypeSampler
|
||||
%6 = OpTypePointer UniformConstant %7
|
||||
%5 = OpVariable %6 UniformConstant
|
||||
%9 = OpTypeInt 32 1
|
||||
%11 = OpTypeVector %9 3
|
||||
)",
|
||||
R"(
|
||||
%12 = OpLoad %3 %1
|
||||
%10 = OpImageQuerySize %11 %12
|
||||
%8 = OpCompositeExtract %9 %10 2
|
||||
)",
|
||||
R"(
|
||||
OpCapability ImageQuery
|
||||
)"};
|
||||
case ValidTextureOverload::kSample1dF32:
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue