Import Tint changes from Dawn
Changes:
- e5a62a88b182f3186d0e80e74209f37a18f1d41c [tintd] Add more comments by Ben Clayton <bclayton@google.com>
- de85a6154309afb1910a2adce669aba89798e319 [tintd] Handle multi-line node spans by Ben Clayton <bclayton@google.com>
- 95b0765dbdde149c273c7057e52ad78a5ed2b559 Fix issue with external texture mapping in MSL. by dan sinclair <dsinclair@chromium.org>
GitOrigin-RevId: e5a62a88b182f3186d0e80e74209f37a18f1d41c
Change-Id: Ife436df9b7adc4870148651faa8c196e554e82f1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/178921
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
index 6cbaec6..f1bd0c3 100644
--- a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
+++ b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
@@ -174,6 +174,12 @@
// Replace the original texture_external binding with a texture_2d<f32> binding.
auto cloned_attributes = ctx.Clone(global->attributes);
+
+ // Allow the originating binding to have collisions.
+ if (new_binding_points->allow_collisions) {
+ cloned_attributes.Push(b.Disable(DisabledValidation::kBindingPointCollision));
+ }
+
const Expression* cloned_initializer = ctx.Clone(global->initializer);
auto* replacement = b.Var(
diff --git a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
index 27f2acb..f89523c 100644
--- a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
@@ -176,6 +176,83 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(MultiplanarExternalTextureTest, Collisions) {
+ auto* src = R"(
+@group(0) @binding(0) var myTexture: texture_external;
+
+@fragment
+fn fragmentMain() -> @location(0) vec4f {
+ let result = textureLoad(myTexture, vec2u(1, 1));
+ return vec4f(1);
+})";
+
+ auto* expect = R"(
+struct GammaTransferParams {
+ G : f32,
+ A : f32,
+ B : f32,
+ C : f32,
+ D : f32,
+ E : f32,
+ F : f32,
+ padding : u32,
+}
+
+struct ExternalTextureParams {
+ numPlanes : u32,
+ doYuvToRgbConversionOnly : u32,
+ yuvToRgbConversionMatrix : mat3x4<f32>,
+ gammaDecodeParams : GammaTransferParams,
+ gammaEncodeParams : GammaTransferParams,
+ gamutConversionMatrix : mat3x3<f32>,
+ coordTransformationMatrix : mat3x2<f32>,
+}
+
+@internal(disable_validation__binding_point_collision) @group(0) @binding(1) var ext_tex_plane_1 : texture_2d<f32>;
+
+@internal(disable_validation__binding_point_collision) @group(0) @binding(0) var<uniform> ext_tex_params : ExternalTextureParams;
+
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var myTexture : texture_2d<f32>;
+
+fn gammaCorrection(v : vec3<f32>, params : GammaTransferParams) -> vec3<f32> {
+ let cond = (abs(v) < vec3<f32>(params.D));
+ let t = (sign(v) * ((params.C * abs(v)) + params.F));
+ let f = (sign(v) * (pow(((params.A * abs(v)) + params.B), vec3<f32>(params.G)) + params.E));
+ return select(f, t, cond);
+}
+
+fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<u32>, params : ExternalTextureParams) -> vec4<f32> {
+ let coord1 = (coord >> vec2<u32>(1));
+ var color : vec4<f32>;
+ if ((params.numPlanes == 1)) {
+ color = textureLoad(plane0, coord, 0).rgba;
+ } else {
+ color = vec4<f32>((vec4<f32>(textureLoad(plane0, coord, 0).r, textureLoad(plane1, coord1, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
+ }
+ if ((params.doYuvToRgbConversionOnly == 0)) {
+ color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
+ color = vec4<f32>((params.gamutConversionMatrix * color.rgb), color.a);
+ color = vec4<f32>(gammaCorrection(color.rgb, params.gammaEncodeParams), color.a);
+ }
+ return color;
+}
+
+@fragment
+fn fragmentMain() -> @location(0) vec4f {
+ let result = textureLoadExternal(myTexture, ext_tex_plane_1, vec2u(1, 1), ext_tex_params);
+ return vec4f(1);
+}
+)";
+
+ DataMap data;
+ data.Add<MultiplanarExternalTexture::NewBindingPoints>(
+ MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 0}}}},
+ /* allow collisions */ true);
+ auto got = Run<MultiplanarExternalTexture>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
// Tests that the transform works with a textureDimensions call.
TEST_F(MultiplanarExternalTextureTest, Dimensions_OutOfOrder) {
auto* src = R"(
diff --git a/src/tint/lang/wgsl/ls/file.h b/src/tint/lang/wgsl/ls/file.h
index 7e6c367..7f31ad9 100644
--- a/src/tint/lang/wgsl/ls/file.h
+++ b/src/tint/lang/wgsl/ls/file.h
@@ -28,6 +28,8 @@
#ifndef SRC_TINT_LANG_WGSL_LS_FILE_H_
#define SRC_TINT_LANG_WGSL_LS_FILE_H_
+#include <cstddef>
+#include <cstdint>
#include <limits>
#include <memory>
#include <string>
@@ -98,17 +100,16 @@
template <typename T = sem::Node, UnwrapMode UNWRAP_MODE = DefaultUnwrapMode<T>>
const T* NodeAt(Source::Location l) const {
// TODO(bclayton): This is a brute-force search. Optimize.
- size_t best_len = std::numeric_limits<uint32_t>::max();
+ size_t best_len = std::numeric_limits<size_t>::max();
const T* best_node = nullptr;
for (auto* node : nodes) {
- if (node->source.range.begin.line == node->source.range.end.line &&
- node->source.range.begin <= l && node->source.range.end >= l) {
+ if (node->source.range.begin <= l && node->source.range.end >= l) {
auto* sem = program.Sem().Get(node);
if constexpr (UNWRAP_MODE == UnwrapMode::kUnwrap) {
sem = Unwrap(sem);
}
if (auto* cast = As<T, CastFlags::kDontErrorOnImpossibleCast>(sem)) {
- size_t len = node->source.range.end.column - node->source.range.begin.column;
+ size_t len = node->source.range.Length(source->content);
if (len < best_len) {
best_len = len;
best_node = cast;
diff --git a/src/tint/lang/wgsl/ls/hover.cc b/src/tint/lang/wgsl/ls/hover.cc
index 5ffbe47..fe9f123 100644
--- a/src/tint/lang/wgsl/ls/hover.cc
+++ b/src/tint/lang/wgsl/ls/hover.cc
@@ -64,6 +64,7 @@
namespace {
+/// @returns a lsp::MarkedStringWithLanguage with the content @p wgsl, using the language `wgsl`
lsp::MarkedStringWithLanguage WGSL(std::string wgsl) {
lsp::MarkedStringWithLanguage str;
str.language = "wgsl";
@@ -71,6 +72,7 @@
return str;
}
+/// PrintConstant() writes the constant value @p val as a WGSL value to the StringStream @p ss
void PrintConstant(const core::constant::Value* val, StringStream& ss) {
Switch(
val, //
@@ -98,6 +100,7 @@
});
}
+/// Variable() writes the hover information for the variable @p v to @p out
void Variable(const sem::Variable* v, std::vector<lsp::MarkedString>& out) {
StringStream ss;
auto* kind = Switch(
@@ -122,6 +125,7 @@
out.push_back(WGSL(ss.str()));
}
+/// Function() writes the hover information for the function @p f to @p out
void Function(const sem::Function* f, std::vector<lsp::MarkedString>& out) {
StringStream ss;
ss << "fn " << f->Declaration()->name->symbol.NameView();
@@ -142,6 +146,8 @@
out.push_back(WGSL(ss.str()));
}
+/// Call() writes the hover information for a call to the function with the name @p name with
+/// semantic info @p c, to @p out
void Call(std::string_view name, const sem::Call* c, std::vector<lsp::MarkedString>& out) {
StringStream ss;
ss << name << "(";
@@ -165,6 +171,7 @@
out.push_back(WGSL(ss.str()));
}
+/// Constant() writes the hover information for the constant value @p val to @p out
void Constant(const core::constant::Value* val, std::vector<lsp::MarkedString>& out) {
StringStream ss;
PrintConstant(val, ss);
diff --git a/src/tint/lang/wgsl/ls/sem_tokens.cc b/src/tint/lang/wgsl/ls/sem_tokens.cc
index 3accd26..ddbd5a5 100644
--- a/src/tint/lang/wgsl/ls/sem_tokens.cc
+++ b/src/tint/lang/wgsl/ls/sem_tokens.cc
@@ -50,12 +50,17 @@
namespace {
+/// Token describes a single semantic token, as returned by TextDocumentSemanticTokensFullRequest.
struct Token {
+ /// The start position of the token
lsp::Position position;
+ /// The kind of token. Maps to enumerators in SemToken.
size_t kind = 0;
+ /// The length of the token in UTF-8 codepoints.
size_t length = 0;
};
+/// @returns a Token built from the source range @p range with the kind @p kind
Token TokenFromRange(const tint::Source::Range& range, SemToken::Kind kind) {
Token tok;
tok.position = Conv(range.begin);
@@ -64,6 +69,8 @@
return tok;
}
+/// @returns the token kind for the expression @p expr, or nullptr if the expression does not have a
+/// token kind.
std::optional<SemToken::Kind> TokenKindFor(const sem::Expression* expr) {
return Switch<std::optional<SemToken::Kind>>(
Unwrap(expr), //
@@ -75,6 +82,7 @@
[](tint::Default) { return std::nullopt; });
}
+/// @returns all the semantic tokens in the file @p file, in sequential order.
std::vector<Token> Tokens(File& file) {
std::vector<Token> tokens;
auto& sem = file.program.Sem();
@@ -102,6 +110,9 @@
tokens.push_back(TokenFromRange(a->member->source.range, SemToken::kMember));
});
}
+ std::sort(tokens.begin(), tokens.end(),
+ [](const Token& a, const Token& b) { return a.position < b.position; });
+
return tokens;
}
@@ -117,9 +128,6 @@
Token last;
auto tokens = Tokens(**file);
- std::sort(tokens.begin(), tokens.end(),
- [](const Token& a, const Token& b) { return a.position < b.position; });
-
for (auto tok : tokens) {
if (last.position.line != tok.position.line) {
last.position.character = 0;
diff --git a/src/tint/lang/wgsl/ls/signature_help.cc b/src/tint/lang/wgsl/ls/signature_help.cc
index 401e621..7644c74 100644
--- a/src/tint/lang/wgsl/ls/signature_help.cc
+++ b/src/tint/lang/wgsl/ls/signature_help.cc
@@ -27,6 +27,7 @@
#include "src/tint/lang/wgsl/ls/server.h"
+#include "langsvr/lsp/comparators.h"
#include "src/tint/lang/core/intrinsic/table.h"
#include "src/tint/lang/wgsl/intrinsic/dialect.h"
#include "src/tint/lang/wgsl/ls/utils.h"
@@ -40,8 +41,10 @@
namespace {
-std::vector<lsp::ParameterInformation> Params(const core::intrinsic::TableData& data,
- const core::intrinsic::OverloadInfo& overload) {
+/// @returns the parameter information for all the parameters of the intrinsic overload @p overload.
+std::vector<lsp::ParameterInformation> Params(const core::intrinsic::OverloadInfo& overload) {
+ auto& data = wgsl::intrinsic::Dialect::kData;
+
std::vector<lsp::ParameterInformation> params;
for (size_t i = 0; i < overload.num_parameters; i++) {
lsp::ParameterInformation param_out;
@@ -56,18 +59,22 @@
return params;
}
-size_t CalcParamIndex(const Source& call_source, const Source::Location& carat) {
+/// @returns the zero-based index of the parameter at with the cursor at @p position, for a call
+/// with the source @p call_source.
+size_t CalcParamIndex(const Source& call_source, const Source::Location& position) {
size_t index = 0;
int depth = 0;
- auto start = call_source.range.begin;
- auto end = std::min(call_source.range.end, carat);
+ auto range = Conv(call_source.range);
+ auto start = range.start;
+ auto end = std::min(range.end, Conv(position));
auto& lines = call_source.file->content.lines;
- for (auto line = start.line; line <= end.line; line++) {
- auto start_column = line == start.line ? start.column : 0;
- auto end_column = line == end.line ? end.column : 0;
- auto text = lines[line - 1].substr(start_column - 1, end_column - start_column);
+ for (auto line_idx = start.line; line_idx <= end.line; line_idx++) {
+ auto& line = lines[line_idx];
+ auto start_character = (line_idx == start.line) ? start.character : 0;
+ auto end_character = (line_idx == end.line) ? end.character : line.size();
+ auto text = line.substr(start_character, end_character - start_character);
for (char c : text) {
switch (c) {
case '(':
@@ -88,6 +95,8 @@
return index;
}
+/// PrintOverload() emits a description of the intrinsic overload @p overload of the function with
+/// name @p intrinsic_name to @p ss.
void PrintOverload(StyledText& ss,
core::intrinsic::Context& context,
const core::intrinsic::OverloadInfo& overload,
@@ -187,7 +196,7 @@
for (size_t i = 0; i < intrinsic_info.num_overloads; i++) {
auto& overload = data[intrinsic_info.overloads + i];
- auto params = Params(data, overload);
+ auto params = Params(overload);
auto type_mgr = core::type::Manager::Wrap(program.Types());
auto symbols = SymbolTable::Wrap(program.Symbols());
diff --git a/src/tint/lang/wgsl/ls/signature_help_test.cc b/src/tint/lang/wgsl/ls/signature_help_test.cc
index ceaf52a..31fcaba 100644
--- a/src/tint/lang/wgsl/ls/signature_help_test.cc
+++ b/src/tint/lang/wgsl/ls/signature_help_test.cc
@@ -271,6 +271,28 @@
}, // =========================================
{
R"(
+const C = max(1
+ ⧘
+ ,
+ 2);
+)",
+ MaxSignatures(),
+ /* active_signature */ 0,
+ /* active_parameter */ 0,
+ }, // =========================================
+ {
+ R"(
+const C = max(1
+ ,
+ ⧘
+ 2);
+)",
+ MaxSignatures(),
+ /* active_signature */ 0,
+ /* active_parameter */ 1,
+ }, // =========================================
+ {
+ R"(
const C = max(1, 2) ⧘;
)",
{},
diff --git a/src/tint/utils/diagnostic/source.cc b/src/tint/utils/diagnostic/source.cc
index 3dc439b..b183f8a 100644
--- a/src/tint/utils/diagnostic/source.cc
+++ b/src/tint/utils/diagnostic/source.cc
@@ -31,6 +31,7 @@
#include <string_view>
#include <utility>
+#include "src/tint/utils/ice/ice.h"
#include "src/tint/utils/text/string_stream.h"
#include "src/tint/utils/text/unicode.h"
@@ -190,4 +191,25 @@
return out.str();
}
+size_t Source::Range::Length(const FileContent& content) const {
+ TINT_ASSERT_OR_RETURN_VALUE(begin <= end, 0);
+ TINT_ASSERT_OR_RETURN_VALUE(begin.column > 0, 0);
+ TINT_ASSERT_OR_RETURN_VALUE(begin.line > 0, 0);
+ TINT_ASSERT_OR_RETURN_VALUE(end.line <= 1 + content.lines.size(), 0);
+ TINT_ASSERT_OR_RETURN_VALUE(end.column <= 1 + content.lines[end.line - 1].size(), 0);
+
+ if (end.line == begin.line) {
+ return end.column - begin.column;
+ }
+
+ size_t len = (content.lines[begin.line - 1].size() + 1 - begin.column) + // first line
+ (end.column - 1) + // last line
+ end.line - begin.line; // newlines
+
+ for (size_t line = begin.line + 1; line < end.line; line++) {
+ len += content.lines[line - 1].size(); // whole-lines
+ }
+ return len;
+}
+
} // namespace tint
diff --git a/src/tint/utils/diagnostic/source.h b/src/tint/utils/diagnostic/source.h
index afef58c..e644122 100644
--- a/src/tint/utils/diagnostic/source.h
+++ b/src/tint/utils/diagnostic/source.h
@@ -42,7 +42,7 @@
/// Source describes a range of characters within a source file.
class Source {
public:
- /// FileContent describes the content of a source file encoded using utf-8.
+ /// FileContent describes the content of a source file encoded using UTF-8.
class FileContent {
public:
/// Constructs the FileContent with the given file content.
@@ -151,7 +151,7 @@
inline constexpr Range(const Location& b, const Location& e) : begin(b), end(e) {}
/// Return a column-shifted Range
- /// @param n the number of characters to shift by
+ /// @param n the number of UTF-8 codepoint to shift by
/// @returns a Range with a #begin and #end column shifted by `n`
inline Range operator+(uint32_t n) const {
return Range{{begin.line, begin.column + n}, {end.line, end.column + n}};
@@ -169,9 +169,16 @@
/// @returns true if `this` == `rhs`
inline bool operator!=(const Range& rhs) const { return !(*this == rhs); }
- /// The location of the first character in the range.
+ /// @param content the file content that this range belongs to
+ /// @returns the length of the range in UTF-8 codepoints, treating all line-break sequences
+ /// as a single code-point.
+ /// @see https://www.w3.org/TR/WGSL/#blankspace-and-line-breaks for the definition of a line
+ /// break.
+ size_t Length(const FileContent& content) const;
+
+ /// The location of the first UTF-8 codepoint in the range.
Location begin;
- /// The location of one-past the last character in the range.
+ /// The location of one-past the last UTF-8 codepoint in the range.
Location end;
};
diff --git a/src/tint/utils/diagnostic/source_test.cc b/src/tint/utils/diagnostic/source_test.cc
index cb50053..42b4e01 100644
--- a/src/tint/utils/diagnostic/source_test.cc
+++ b/src/tint/utils/diagnostic/source_test.cc
@@ -28,6 +28,7 @@
#include "src/tint/utils/diagnostic/source.h"
#include <memory>
+#include <string_view>
#include <utility>
#include "gtest/gtest.h"
@@ -35,7 +36,7 @@
namespace tint {
namespace {
-static constexpr const char* kSource = R"(line one
+static constexpr std::string_view kSource = R"(line one
line two
line three)";
@@ -81,7 +82,7 @@
#define kLS "\xE2\x80\xA8"
#define kPS "\xE2\x80\xA9"
-using LineBreakTest = testing::TestWithParam<const char*>;
+using LineBreakTest = testing::TestWithParam<std::string_view>;
TEST_P(LineBreakTest, Single) {
std::string src = "line one";
src += GetParam();
@@ -108,5 +109,50 @@
LineBreakTest,
testing::Values(kVTab, kFF, kNL, kLS, kPS, kLF, kCR, kCR kLF));
+using RangeLengthTest = testing::TestWithParam<std::pair<Source::Range, size_t>>;
+TEST_P(RangeLengthTest, Test) {
+ Source::FileContent fc("X" kLF // 1
+ "XX" kCR kLF // 2
+ "X" kCR // 3
+ kLS // 4
+ "XX" // 5
+ );
+ auto& range = GetParam().first;
+ auto expected_length = GetParam().second;
+ EXPECT_EQ(range.Length(fc), expected_length);
+}
+
+INSTANTIATE_TEST_SUITE_P(SingleLine,
+ RangeLengthTest,
+ testing::Values( //
+
+ std::make_pair(Source::Range{{1, 1}, {1, 1}}, 0),
+ std::make_pair(Source::Range{{2, 1}, {2, 1}}, 0),
+ std::make_pair(Source::Range{{3, 1}, {3, 1}}, 0),
+ std::make_pair(Source::Range{{4, 1}, {4, 1}}, 0),
+ std::make_pair(Source::Range{{5, 1}, {5, 1}}, 0),
+
+ std::make_pair(Source::Range{{1, 1}, {1, 2}}, 1),
+ std::make_pair(Source::Range{{2, 1}, {2, 3}}, 2),
+ std::make_pair(Source::Range{{3, 1}, {3, 2}}, 1),
+ std::make_pair(Source::Range{{5, 1}, {5, 3}}, 2),
+
+ std::make_pair(Source::Range{{1, 2}, {1, 2}}, 0),
+ std::make_pair(Source::Range{{2, 2}, {2, 3}}, 1),
+ std::make_pair(Source::Range{{3, 2}, {3, 2}}, 0),
+ std::make_pair(Source::Range{{5, 2}, {5, 3}}, 1)));
+
+INSTANTIATE_TEST_SUITE_P(MultiLine,
+ RangeLengthTest,
+ testing::Values( //
+
+ std::make_pair(Source::Range{{1, 1}, {2, 1}}, 2),
+ std::make_pair(Source::Range{{2, 1}, {3, 1}}, 3),
+ std::make_pair(Source::Range{{3, 1}, {4, 1}}, 2),
+ std::make_pair(Source::Range{{4, 1}, {5, 1}}, 1),
+
+ std::make_pair(Source::Range{{1, 1}, {5, 3}}, 10),
+ std::make_pair(Source::Range{{2, 2}, {5, 2}}, 6)));
+
} // namespace
} // namespace tint