mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-14 03:11:29 +00:00
Add a new 'Target' to the ast::CallExpression, which can be either an Identifier or Type. The Identifier may resolve to a Type, if the Type is a structure or alias. The Resolver now resolves the CallExpression target to one of the following sem::CallTargets: * sem::Function * sem::Intrinsic * sem::TypeConstructor * sem::TypeCast This change will allow us to remove the type tracking logic from the WGSL parser, which is required for out-of-order module scope declarations. Bug: tint:888 Bug: tint:1266 Change-Id: I696f117115a50981fd5c102a0d7764641bb755dd Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68525 Reviewed-by: David Neto <dneto@google.com> Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
134 lines
5.6 KiB
C++
134 lines
5.6 KiB
C++
// Copyright 2021 The Tint Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "src/transform/external_texture_transform.h"
|
|
|
|
#include "src/program_builder.h"
|
|
#include "src/sem/call.h"
|
|
#include "src/sem/variable.h"
|
|
|
|
TINT_INSTANTIATE_TYPEINFO(tint::transform::ExternalTextureTransform);
|
|
|
|
namespace tint {
|
|
namespace transform {
|
|
|
|
ExternalTextureTransform::ExternalTextureTransform() = default;
|
|
ExternalTextureTransform::~ExternalTextureTransform() = default;
|
|
|
|
void ExternalTextureTransform::Run(CloneContext& ctx,
|
|
const DataMap&,
|
|
DataMap&) {
|
|
auto& sem = ctx.src->Sem();
|
|
|
|
// Within this transform, usages of texture_external are replaced with a
|
|
// texture_2d<f32>, which will allow us perform operations on a
|
|
// texture_external without maintaining texture_external-specific code
|
|
// generation paths in the backends.
|
|
|
|
// When replacing instances of texture_external with texture_2d<f32> we must
|
|
// also modify calls to the texture_external overloads of textureLoad and
|
|
// textureSampleLevel, which unlike their texture_2d<f32> overloads do not
|
|
// require a level parameter. To do this we identify calls to textureLoad and
|
|
// textureSampleLevel that use texture_external as the first parameter and add
|
|
// a parameter for the level (which is always 0).
|
|
|
|
// Scan the AST nodes for calls to textureLoad or textureSampleLevel.
|
|
for (auto* node : ctx.src->ASTNodes().Objects()) {
|
|
if (auto* call_expr = node->As<ast::CallExpression>()) {
|
|
if (auto* intrinsic =
|
|
sem.Get(call_expr)->Target()->As<sem::Intrinsic>()) {
|
|
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad ||
|
|
intrinsic->Type() == sem::IntrinsicType::kTextureSampleLevel) {
|
|
// When a textureLoad or textureSampleLevel has been identified, check
|
|
// if the first parameter is an external texture.
|
|
if (auto* var =
|
|
sem.Get(call_expr->args[0])->As<sem::VariableUser>()) {
|
|
if (var->Variable()
|
|
->Type()
|
|
->UnwrapRef()
|
|
->Is<sem::ExternalTexture>()) {
|
|
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad &&
|
|
call_expr->args.size() != 2) {
|
|
TINT_ICE(Transform, ctx.dst->Diagnostics())
|
|
<< "expected textureLoad call with a texture_external to "
|
|
"have 2 parameters, found "
|
|
<< call_expr->args.size() << " parameters";
|
|
}
|
|
|
|
if (intrinsic->Type() ==
|
|
sem::IntrinsicType::kTextureSampleLevel &&
|
|
call_expr->args.size() != 3) {
|
|
TINT_ICE(Transform, ctx.dst->Diagnostics())
|
|
<< "expected textureSampleLevel call with a "
|
|
"texture_external to have 3 parameters, found "
|
|
<< call_expr->args.size() << " parameters";
|
|
}
|
|
|
|
// Replace the call with another that has the same parameters in
|
|
// addition to a level parameter (always zero for external
|
|
// textures).
|
|
auto* exp = ctx.Clone(call_expr->target.name);
|
|
auto* externalTextureParam = ctx.Clone(call_expr->args[0]);
|
|
|
|
ast::ExpressionList params;
|
|
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad) {
|
|
auto* coordsParam = ctx.Clone(call_expr->args[1]);
|
|
auto* levelParam = ctx.dst->Expr(0);
|
|
params = {externalTextureParam, coordsParam, levelParam};
|
|
} else if (intrinsic->Type() ==
|
|
sem::IntrinsicType::kTextureSampleLevel) {
|
|
auto* samplerParam = ctx.Clone(call_expr->args[1]);
|
|
auto* coordsParam = ctx.Clone(call_expr->args[2]);
|
|
auto* levelParam = ctx.dst->Expr(0.0f);
|
|
params = {externalTextureParam, samplerParam, coordsParam,
|
|
levelParam};
|
|
}
|
|
|
|
auto* newCall = ctx.dst->create<ast::CallExpression>(exp, params);
|
|
ctx.Replace(call_expr, newCall);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Scan the AST nodes for external texture declarations.
|
|
for (auto* node : ctx.src->ASTNodes().Objects()) {
|
|
if (auto* var = node->As<ast::Variable>()) {
|
|
if (::tint::Is<ast::ExternalTexture>(var->type)) {
|
|
// Replace a single-plane external texture with a 2D, f32 sampled
|
|
// texture.
|
|
auto* newType = ctx.dst->ty.sampled_texture(ast::TextureDimension::k2d,
|
|
ctx.dst->ty.f32());
|
|
auto clonedSrc = ctx.Clone(var->source);
|
|
auto clonedSym = ctx.Clone(var->symbol);
|
|
auto* clonedConstructor = ctx.Clone(var->constructor);
|
|
auto clonedDecorations = ctx.Clone(var->decorations);
|
|
auto* newVar = ctx.dst->create<ast::Variable>(
|
|
clonedSrc, clonedSym, var->declared_storage_class,
|
|
var->declared_access, newType, var->is_const, clonedConstructor,
|
|
clonedDecorations);
|
|
|
|
ctx.Replace(var, newVar);
|
|
}
|
|
}
|
|
}
|
|
|
|
ctx.Clone();
|
|
}
|
|
|
|
} // namespace transform
|
|
} // namespace tint
|