Implement textureDimensions()

SPIR-V reader TODO.

Bug: tint:140
Bug: tint:437
Change-Id: Ia3a6cb0b36142142d3dc8662281e1860c609c82b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/36980
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton 2021-01-11 21:07:32 +00:00 committed by Commit Bot service account
parent c3c70f848a
commit 4a0b9f77ef
15 changed files with 1866 additions and 154 deletions

View File

@ -262,13 +262,18 @@ bool IsFloatClassificationIntrinsic(Intrinsic i) {
}
bool IsTextureIntrinsic(Intrinsic i) {
return i == Intrinsic::kTextureLoad || i == Intrinsic::kTextureSample ||
return i == Intrinsic::kTextureDimensions || i == Intrinsic::kTextureLoad ||
i == Intrinsic::kTextureSample ||
i == Intrinsic::kTextureSampleLevel ||
i == Intrinsic::kTextureSampleBias ||
i == Intrinsic::kTextureSampleCompare ||
i == Intrinsic::kTextureSampleGrad || i == Intrinsic::kTextureStore;
}
bool IsImageQueryIntrinsic(Intrinsic i) {
return i == ast::Intrinsic::kTextureDimensions;
}
} // namespace intrinsic
} // namespace ast
} // namespace tint

View File

@ -84,6 +84,7 @@ enum class Intrinsic {
kStep,
kTan,
kTanh,
kTextureDimensions,
kTextureLoad,
kTextureSample,
kTextureSampleBias,
@ -187,6 +188,11 @@ bool IsFloatClassificationIntrinsic(Intrinsic i);
/// @returns true if the given `i` is a texture operation intrinsic
bool IsTextureIntrinsic(Intrinsic i);
/// Determines if the given `i` is a image query intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a image query intrinsic
bool IsImageQueryIntrinsic(Intrinsic i);
} // namespace intrinsic
} // namespace ast
} // namespace tint

View File

@ -186,6 +186,344 @@ ast::Variable* TextureOverloadCase::buildSamplerVariable(
std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
return {
{
ValidTextureOverload::kDimensions1d,
"textureDimensions(t : texture_1d<f32>) -> i32",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k1d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensions1dArray,
"textureDimensions(t : texture_1d_array<f32>) -> i32",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k1dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensions2d,
"textureDimensions(t : texture_2d<f32>) -> vec2<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensions2dLevel,
"textureDimensions(t : texture_2d<f32>,\n"
" level : i32) -> vec2<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensions2dArray,
"textureDimensions(t : texture_2d_array<f32>) -> vec2<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensions2dArrayLevel,
"textureDimensions(t : texture_2d_array<f32>,\n"
" level : i32) -> vec2<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensions3d,
"textureDimensions(t : texture_3d<f32>) -> vec3<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k3d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensions3dLevel,
"textureDimensions(t : texture_3d<f32>,\n"
" level : i32) -> vec3<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k3d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensionsCube,
"textureDimensions(t : texture_cube<f32>) -> vec3<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::kCube,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsCubeLevel,
"textureDimensions(t : texture_cube<f32>,\n"
" level : i32) -> vec3<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::kCube,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensionsCubeArray,
"textureDimensions(t : texture_cube_array<f32>) -> vec3<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::kCubeArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsCubeArrayLevel,
"textureDimensions(t : texture_cube_array<f32>,\n"
" level : i32) -> vec3<i32>",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::kCubeArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensionsMultisampled_2d,
"textureDimensions(t : texture_multisampled_2d<f32>)-> vec2<i32>",
TextureKind::kMultisampled,
type::SamplerKind::kSampler,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsMultisampled_2dArray,
"textureDimensions(t : texture_multisampled_2d_array<f32>)-> "
"vec2<i32>",
TextureKind::kMultisampled,
type::SamplerKind::kSampler,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsDepth2d,
"textureDimensions(t : texture_depth_2d) -> vec2<i32>",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsDepth2dLevel,
"textureDimensions(t : texture_depth_2d,\n"
" level : i32) -> vec2<i32>",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensionsDepth2dArray,
"textureDimensions(t : texture_depth_2d_array) -> vec2<i32>",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsDepth2dArrayLevel,
"textureDimensions(t : texture_depth_2d_array,\n"
" level : i32) -> vec2<i32>",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensionsDepthCube,
"textureDimensions(t : texture_depth_cube) -> vec3<i32>",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::kCube,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsDepthCubeLevel,
"textureDimensions(t : texture_depth_cube,\n"
" level : i32) -> vec3<i32>",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::kCube,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensionsDepthCubeArray,
"textureDimensions(t : texture_depth_cube_array) -> vec3<i32>",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::kCubeArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsDepthCubeArrayLevel,
"textureDimensions(t : texture_depth_cube_array,\n"
" level : i32) -> vec3<i32>",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::kCubeArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture", 1); },
},
{
ValidTextureOverload::kDimensionsStorageRO1d,
"textureDimensions(t : texture_storage_ro_1d<rgba32float>) -> i32",
ast::AccessControl::kReadOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k1d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageRO1dArray,
"textureDimensions(t : texture_storage_ro_1d_array<rgba32float>) -> "
"i32",
ast::AccessControl::kReadOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k1dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageRO2d,
"textureDimensions(t : texture_storage_ro_2d<rgba32float>) -> "
"vec2<i32>",
ast::AccessControl::kReadOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageRO2dArray,
"textureDimensions(t : texture_storage_ro_2d_array<rgba32float>) -> "
"vec2<i32>",
ast::AccessControl::kReadOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageRO3d,
"textureDimensions(t : texture_storage_ro_3d<rgba32float>) -> "
"vec3<i32>",
ast::AccessControl::kReadOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k3d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageWO1d,
"textureDimensions(t : texture_storage_wo_1d<rgba32float>) -> i32",
ast::AccessControl::kWriteOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k1d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageWO1dArray,
"textureDimensions(t : texture_storage_wo_1d_array<rgba32float>) -> "
"i32",
ast::AccessControl::kWriteOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k1dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageWO2d,
"textureDimensions(t : texture_storage_wo_2d<rgba32float>) -> "
"vec2<i32>",
ast::AccessControl::kWriteOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageWO2dArray,
"textureDimensions(t : texture_storage_wo_2d_array<rgba32float>) -> "
"vec2<i32>",
ast::AccessControl::kWriteOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kDimensionsStorageWO3d,
"textureDimensions(t : texture_storage_wo_3d<rgba32float>) -> "
"vec3<i32>",
ast::AccessControl::kWriteOnly,
ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k3d,
TextureDataType::kF32,
"textureDimensions",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kSample1dF32,
"textureSample(t : texture_1d<f32>,\n"

View File

@ -36,6 +36,38 @@ std::ostream& operator<<(std::ostream& out, const TextureDataType& ty);
/// Non-exhaustive list of valid texture overloads
enum class ValidTextureOverload {
kDimensions1d,
kDimensions1dArray,
kDimensions2d,
kDimensions2dLevel,
kDimensions2dArray,
kDimensions2dArrayLevel,
kDimensions3d,
kDimensions3dLevel,
kDimensionsCube,
kDimensionsCubeLevel,
kDimensionsCubeArray,
kDimensionsCubeArrayLevel,
kDimensionsMultisampled_2d,
kDimensionsMultisampled_2dArray,
kDimensionsDepth2d,
kDimensionsDepth2dLevel,
kDimensionsDepth2dArray,
kDimensionsDepth2dArrayLevel,
kDimensionsDepthCube,
kDimensionsDepthCubeLevel,
kDimensionsDepthCubeArray,
kDimensionsDepthCubeArrayLevel,
kDimensionsStorageRO1d,
kDimensionsStorageRO1dArray,
kDimensionsStorageRO2d,
kDimensionsStorageRO2dArray,
kDimensionsStorageRO3d,
kDimensionsStorageWO1d,
kDimensionsStorageWO1dArray,
kDimensionsStorageWO2d,
kDimensionsStorageWO2dArray,
kDimensionsStorageWO3d,
kSample1dF32,
kSample1dArrayF32,
kSample2dF32,

View File

@ -56,6 +56,22 @@ std::ostream& operator<<(std::ostream& out, TextureDimension dim) {
return out;
}
bool IsTextureArray(TextureDimension dim) {
switch (dim) {
case TextureDimension::k1dArray:
case TextureDimension::k2dArray:
case TextureDimension::kCubeArray:
return true;
case TextureDimension::k2d:
case TextureDimension::kNone:
case TextureDimension::k1d:
case TextureDimension::k3d:
case TextureDimension::kCube:
return false;
}
return false;
}
Texture::Texture(TextureDimension dim) : dim_(dim) {}
Texture::Texture(Texture&&) = default;

View File

@ -42,6 +42,10 @@ enum class TextureDimension {
};
std::ostream& operator<<(std::ostream& out, TextureDimension dim);
/// @param dim the TextureDimension to query
/// @return true if the given TextureDimension is an array texture
bool IsTextureArray(TextureDimension dim);
/// A texture type.
class Texture : public Castable<Texture, Type> {
public:

View File

@ -556,18 +556,15 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
->UnwrapPtrIfNeeded()
->As<ast::type::Texture>();
bool is_array = false;
bool is_array = ast::type::IsTextureArray(texture->dim());
bool is_multisampled = texture->Is<ast::type::MultisampledTexture>();
switch (texture->dim()) {
case ast::type::TextureDimension::k1dArray:
case ast::type::TextureDimension::k2dArray:
case ast::type::TextureDimension::kCubeArray:
is_array = true;
break;
default:
break;
}
switch (ident->intrinsic()) {
case ast::Intrinsic::kTextureDimensions:
param.idx.texture = param.count++;
if (expr->params().size() > param.count) {
param.idx.level = param.count++;
}
break;
case ast::Intrinsic::kTextureLoad:
param.idx.texture = param.count++;
param.idx.coords = param.count++;
@ -671,7 +668,27 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
// Set the function return type
ast::type::Type* return_type = nullptr;
if (ident->intrinsic() == ast::Intrinsic::kTextureStore) {
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>()) {
@ -1025,6 +1042,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
ident->set_intrinsic(ast::Intrinsic::kTan);
} else if (name == "tanh") {
ident->set_intrinsic(ast::Intrinsic::kTanh);
} else if (name == "textureDimensions") {
ident->set_intrinsic(ast::Intrinsic::kTextureDimensions);
} else if (name == "textureLoad") {
ident->set_intrinsic(ast::Intrinsic::kTextureLoad);
} else if (name == "textureStore") {

View File

@ -1812,6 +1812,7 @@ INSTANTIATE_TEST_SUITE_P(
IntrinsicData{"step", ast::Intrinsic::kStep},
IntrinsicData{"tan", ast::Intrinsic::kTan},
IntrinsicData{"tanh", ast::Intrinsic::kTanh},
IntrinsicData{"textureDimensions", ast::Intrinsic::kTextureDimensions},
IntrinsicData{"textureLoad", ast::Intrinsic::kTextureLoad},
IntrinsicData{"textureSample", ast::Intrinsic::kTextureSample},
IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias},
@ -2953,6 +2954,40 @@ const char* expected_texture_overload(
ast::intrinsic::test::ValidTextureOverload overload) {
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
switch (overload) {
case ValidTextureOverload::kDimensions1d:
case ValidTextureOverload::kDimensions1dArray:
case ValidTextureOverload::kDimensions2d:
case ValidTextureOverload::kDimensions2dArray:
case ValidTextureOverload::kDimensions3d:
case ValidTextureOverload::kDimensionsCube:
case ValidTextureOverload::kDimensionsCubeArray:
case ValidTextureOverload::kDimensionsMultisampled_2d:
case ValidTextureOverload::kDimensionsMultisampled_2dArray:
case ValidTextureOverload::kDimensionsDepth2d:
case ValidTextureOverload::kDimensionsDepth2dArray:
case ValidTextureOverload::kDimensionsDepthCube:
case ValidTextureOverload::kDimensionsDepthCubeArray:
case ValidTextureOverload::kDimensionsStorageRO1d:
case ValidTextureOverload::kDimensionsStorageRO1dArray:
case ValidTextureOverload::kDimensionsStorageRO2d:
case ValidTextureOverload::kDimensionsStorageRO2dArray:
case ValidTextureOverload::kDimensionsStorageRO3d:
case ValidTextureOverload::kDimensionsStorageWO1d:
case ValidTextureOverload::kDimensionsStorageWO1dArray:
case ValidTextureOverload::kDimensionsStorageWO2d:
case ValidTextureOverload::kDimensionsStorageWO2dArray:
case ValidTextureOverload::kDimensionsStorageWO3d:
return R"(textureDimensions(texture))";
case ValidTextureOverload::kDimensions2dLevel:
case ValidTextureOverload::kDimensions2dArrayLevel:
case ValidTextureOverload::kDimensions3dLevel:
case ValidTextureOverload::kDimensionsCubeLevel:
case ValidTextureOverload::kDimensionsCubeArrayLevel:
case ValidTextureOverload::kDimensionsDepth2dLevel:
case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
case ValidTextureOverload::kDimensionsDepthCubeLevel:
case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
return R"(textureDimensions(texture, level))";
case ValidTextureOverload::kSample1dF32:
return R"(textureSample(texture, sampler, coords))";
case ValidTextureOverload::kSample1dArrayF32:
@ -3176,7 +3211,27 @@ TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
ASSERT_TRUE(td()->Determine()) << td()->error();
ASSERT_TRUE(td()->DetermineResultType(call)) << td()->error();
if (std::string(param.function) == "textureStore") {
if (std::string(param.function) == "textureDimensions") {
switch (param.texture_dimension) {
default:
FAIL() << "invalid texture dimensions: " << param.texture_dimension;
case ast::type::TextureDimension::k1d:
case ast::type::TextureDimension::k1dArray:
EXPECT_EQ(call->result_type()->type_name(), ty.i32->type_name());
break;
case ast::type::TextureDimension::k2d:
case ast::type::TextureDimension::k2dArray:
EXPECT_EQ(call->result_type()->type_name(),
ty.vec2<i32>()->type_name());
break;
case ast::type::TextureDimension::k3d:
case ast::type::TextureDimension::kCube:
case ast::type::TextureDimension::kCubeArray:
EXPECT_EQ(call->result_type()->type_name(),
ty.vec3<i32>()->type_name());
break;
}
} else if (std::string(param.function) == "textureStore") {
EXPECT_EQ(call->result_type(), ty.void_);
} else {
switch (param.texture_kind) {

View File

@ -736,6 +736,39 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
auto* texture = params[pidx.texture];
auto* texture_type = texture->result_type()->UnwrapPtrIfNeeded();
if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) {
// Declare a variable to hold the texture dimensions
auto dims = namer_->GenerateName(kTempNamePrefix);
EmitType(pre, expr->result_type(), Symbol());
pre << " " << dims << ";" << std::endl;
// 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 << ", ";
}
if (auto* vec = expr->result_type()->As<ast::type::Vector>()) {
for (uint32_t i = 0; i < vec->size(); i++) {
if (i > 0) {
pre << ", ";
}
pre << dims << "[" << i << "]";
}
} else {
pre << dims;
}
pre << ");";
// The result of the textureDimensions() call is now the temporary variable.
out << dims;
return true;
}
if (!EmitExpression(pre, out, texture))
return false;

View File

@ -350,10 +350,6 @@ class GeneratorImpl {
/// @returns the index string, or blank if unable to generate
std::string generate_storage_buffer_index_expression(std::ostream& pre,
ast::Expression* expr);
/// Generates a name for the prefix
/// @param prefix the prefix of the name to generate
/// @returns the name
std::string generate_name(const std::string& prefix);
/// Generates an intrinsic name from the given name
/// @param intrinsic the intrinsic to convert to a name
/// @returns the intrinsic name or blank on error

View File

@ -29,10 +29,77 @@ namespace writer {
namespace hlsl {
namespace {
std::string expected_texture_overload(
struct ExpectedResult {
ExpectedResult(const char* o) : out(o) {} // NOLINT
ExpectedResult(const char* p, const char* o) : pre(p), out(o) {}
std::string pre;
std::string out;
};
ExpectedResult expected_texture_overload(
ast::intrinsic::test::ValidTextureOverload 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"
"test_texture.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:
return {
"int2 _tint_tmp;\n"
"test_texture.GetDimensions(_tint_tmp[0], _tint_tmp[1]);",
"_tint_tmp",
};
case ValidTextureOverload::kDimensions3d:
case ValidTextureOverload::kDimensionsCube:
case ValidTextureOverload::kDimensionsCubeArray:
case ValidTextureOverload::kDimensionsDepthCube:
case ValidTextureOverload::kDimensionsDepthCubeArray:
case ValidTextureOverload::kDimensionsStorageRO3d:
case ValidTextureOverload::kDimensionsStorageWO3d:
return {
"int3 _tint_tmp;\n"
"test_texture.GetDimensions(_tint_tmp[0], _tint_tmp[1], "
"_tint_tmp[2]);",
"_tint_tmp",
};
case ValidTextureOverload::kDimensions2dLevel:
case ValidTextureOverload::kDimensions2dArrayLevel:
case ValidTextureOverload::kDimensionsDepth2dLevel:
case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
return {
"int2 _tint_tmp;\n"
"test_texture.GetDimensions(1, _tint_tmp[0], _tint_tmp[1]);",
"_tint_tmp",
};
case ValidTextureOverload::kDimensions3dLevel:
case ValidTextureOverload::kDimensionsCubeLevel:
case ValidTextureOverload::kDimensionsCubeArrayLevel:
case ValidTextureOverload::kDimensionsDepthCubeLevel:
case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
return {
"int3 _tint_tmp;\n"
"test_texture.GetDimensions(1, _tint_tmp[0], _tint_tmp[1], "
"_tint_tmp[2]);",
"_tint_tmp",
};
case ValidTextureOverload::kSample1dF32:
return R"(test_texture.Sample(test_sampler, 1.0f))";
case ValidTextureOverload::kSample1dArrayF32:
@ -282,10 +349,10 @@ TEST_P(HlslGeneratorIntrinsicTextureTest, Call) {
ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error();
EXPECT_TRUE(pre_result().empty());
auto expected = expected_texture_overload(param.overload);
EXPECT_EQ(result(), expected);
EXPECT_EQ(expected.pre, pre_result());
EXPECT_EQ(expected.out, result());
}
INSTANTIATE_TEST_SUITE_P(

View File

@ -652,6 +652,49 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
auto& pidx = signature->params.idx;
auto const kNotUsed = ast::intrinsic::TextureSignature::Parameters::kNotUsed;
if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) {
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;
};
size_t dims = 1;
if (auto* vec = expr->result_type()->As<ast::type::Vector>()) {
dims = vec->size();
}
switch (dims) {
case 1:
get_dim("width");
break;
case 2:
EmitType(expr->result_type(), Symbol());
out_ << "(";
get_dim("width");
out_ << ", ";
get_dim("height");
out_ << ")";
break;
case 3:
EmitType(expr->result_type(), Symbol());
out_ << "(";
get_dim("width");
out_ << ", ";
get_dim("height");
out_ << ", ";
get_dim("depth");
out_ << ")";
break;
}
return true;
}
if (!EmitExpression(params[pidx.texture]))
return false;

View File

@ -33,6 +33,43 @@ std::string expected_texture_overload(
ast::intrinsic::test::ValidTextureOverload 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 R"(test_texture.get_width())";
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:
return R"(int2(test_texture.get_width(), test_texture.get_height()))";
case ValidTextureOverload::kDimensions3d:
case ValidTextureOverload::kDimensionsCube:
case ValidTextureOverload::kDimensionsCubeArray:
case ValidTextureOverload::kDimensionsDepthCube:
case ValidTextureOverload::kDimensionsDepthCubeArray:
case ValidTextureOverload::kDimensionsStorageRO3d:
case ValidTextureOverload::kDimensionsStorageWO3d:
return R"(int3(test_texture.get_width(), test_texture.get_height(), test_texture.get_depth()))";
case ValidTextureOverload::kDimensions2dLevel:
case ValidTextureOverload::kDimensions2dArrayLevel:
case ValidTextureOverload::kDimensionsDepth2dLevel:
case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
return R"(int2(test_texture.get_width(1), test_texture.get_height(1)))";
case ValidTextureOverload::kDimensions3dLevel:
case ValidTextureOverload::kDimensionsCubeLevel:
case ValidTextureOverload::kDimensionsCubeArrayLevel:
case ValidTextureOverload::kDimensionsDepthCubeLevel:
case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
return R"(int3(test_texture.get_width(1), test_texture.get_height(1), test_texture.get_depth(1)))";
case ValidTextureOverload::kSample1dF32:
return R"(test_texture.sample(test_sampler, 1.0f))";
case ValidTextureOverload::kSample1dArrayF32:
@ -275,7 +312,7 @@ TEST_P(MslGeneratorIntrinsicTextureTest, Call) {
ASSERT_TRUE(gen.EmitExpression(call)) << gen.error();
auto expected = expected_texture_overload(param.overload);
EXPECT_EQ(gen.result(), expected);
EXPECT_EQ(expected, gen.result());
}
INSTANTIATE_TEST_SUITE_P(

View File

@ -1850,6 +1850,15 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident,
auto intrinsic = ident->intrinsic();
if (ast::intrinsic::IsFineDerivative(intrinsic) ||
ast::intrinsic::IsCoarseDerivative(intrinsic)) {
push_capability(SpvCapabilityDerivativeControl);
}
if (ast::intrinsic::IsImageQueryIntrinsic(intrinsic)) {
push_capability(SpvCapabilityImageQuery);
}
if (ast::intrinsic::IsTextureIntrinsic(intrinsic)) {
if (!GenerateTextureIntrinsic(ident, call, Operand::Int(result_type_id),
result)) {
@ -1860,11 +1869,6 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident,
OperandList params = {Operand::Int(result_type_id), result};
if (ast::intrinsic::IsFineDerivative(intrinsic) ||
ast::intrinsic::IsCoarseDerivative(intrinsic)) {
push_capability(SpvCapabilityDerivativeControl);
}
spv::Op op = spv::Op::OpNop;
if (intrinsic == ast::Intrinsic::kAny) {
op = spv::Op::OpAny;
@ -1982,8 +1986,8 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident,
bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
ast::CallExpression* call,
spirv::Operand result_type,
spirv::Operand result_id) {
Operand result_type,
Operand result_id) {
auto* texture_type =
call->params()[0]->result_type()->UnwrapAll()->As<ast::type::Texture>();
@ -2008,22 +2012,26 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
return Operand::Int(val_id);
};
// Custom function to call after the texture-intrinsic op has been generated.
std::function<bool()> post_emission = [] { return true; };
// Populate the spirv_params with common parameters
OperandList spirv_params;
spirv_params.reserve(8); // Enough to fit most parameter lists
if (ident->intrinsic() != ast::Intrinsic::kTextureStore) {
spirv_params.emplace_back(std::move(result_type));
spirv_params.emplace_back(std::move(result_id));
}
// Extra image operands, appended to spirv_params.
struct ImageOperand {
SpvImageOperandsMask mask;
tint::writer::spirv::Operand operand;
Operand operand;
};
std::vector<ImageOperand> image_operands;
image_operands.reserve(4); // Enough to fit most parameter lists
auto append_result_type_and_id_to_spirv_params = [&]() {
spirv_params.emplace_back(std::move(result_type));
spirv_params.emplace_back(std::move(result_id));
};
auto append_coords_to_spirv_params = [&]() -> bool {
if (pidx.array_index != kNotUsed) {
// Array index needs to be appended to the coordinates.
@ -2062,10 +2070,67 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
};
switch (ident->intrinsic()) {
case ast::Intrinsic::kTextureDimensions: {
if (ast::type::IsTextureArray(texture_type->dim())) {
// OpImageQuerySize[Lod] will append another element to the returned
// vector describing the number of array elements. textureDimensions()
// does not include this in the returned vector, so it needs to be
// stripped from the resulting vector.
auto unstripped_result = result_op();
ast::type::Type* unstripped_result_type;
if (auto* v = call->result_type()->As<ast::type::Vector>()) {
unstripped_result_type =
mod_->create<ast::type::Vector>(v->type(), v->size() + 1);
post_emission = [=] {
// Swizzle the unstripped vector to form a vec2 or vec3
OperandList operands{
result_type,
result_id,
unstripped_result,
unstripped_result,
};
for (uint32_t i = 0; i < v->size(); i++) {
operands.emplace_back(Operand::Int(i));
}
return push_function_inst(spv::Op::OpVectorShuffle, operands);
};
} else {
unstripped_result_type =
mod_->create<ast::type::Vector>(call->result_type(), 2);
post_emission = [=] {
// Extract the first element of the unstripped vec2 to form a scalar
return push_function_inst(
spv::Op::OpCompositeExtract,
{result_type, result_id, unstripped_result, Operand::Int(0)});
};
}
auto unstripped_result_type_id =
GenerateTypeIfNeeded(unstripped_result_type);
if (unstripped_result_type_id == 0) {
return false;
}
spirv_params.emplace_back(Operand::Int(unstripped_result_type_id));
spirv_params.emplace_back(unstripped_result);
} else {
append_result_type_and_id_to_spirv_params();
}
spirv_params.emplace_back(gen_param(pidx.texture));
if (pidx.level != kNotUsed) {
op = spv::Op::OpImageQuerySizeLod;
spirv_params.emplace_back(gen_param(pidx.level));
} else {
op = spv::Op::OpImageQuerySize;
}
break;
}
case ast::Intrinsic::kTextureLoad: {
op = texture_type->Is<ast::type::StorageTexture>()
? spv::Op::OpImageRead
: spv::Op::OpImageFetch;
append_result_type_and_id_to_spirv_params();
spirv_params.emplace_back(gen_param(pidx.texture));
if (!append_coords_to_spirv_params()) {
return false;
@ -2094,6 +2159,7 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
}
case ast::Intrinsic::kTextureSample: {
op = spv::Op::OpImageSampleImplicitLod;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
return false;
}
@ -2101,6 +2167,7 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
}
case ast::Intrinsic::kTextureSampleBias: {
op = spv::Op::OpImageSampleImplicitLod;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
return false;
}
@ -2111,6 +2178,7 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
}
case ast::Intrinsic::kTextureSampleLevel: {
op = spv::Op::OpImageSampleExplicitLod;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
return false;
}
@ -2121,6 +2189,7 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
}
case ast::Intrinsic::kTextureSampleGrad: {
op = spv::Op::OpImageSampleExplicitLod;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
return false;
}
@ -2134,6 +2203,7 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
}
case ast::Intrinsic::kTextureSampleCompare: {
op = spv::Op::OpImageSampleDrefExplicitLod;
append_result_type_and_id_to_spirv_params();
if (!append_image_and_coords_to_spirv_params()) {
return false;
}
@ -2175,7 +2245,11 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
return false;
}
return push_function_inst(op, spirv_params);
if (!push_function_inst(op, spirv_params)) {
return false;
}
return post_emission();
}
uint32_t Builder::GenerateSampledImage(ast::type::Type* texture_type,

File diff suppressed because it is too large Load Diff