mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-12 22:56:09 +00:00
tint/intrinsics: Texture queries now return unsigned integer / vectors
To match the spec. Also add a bunch of missing texture test cases to src/tint/ast/builtin_texture_helper_test.cc. Fix all the tests that were broken because these were not being exercised. Fixed: tint:1526 Change-Id: I207b51d307bbdc054b595e0e0e0fd3330607e171 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106681 Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Auto-Submit: Ben Clayton <bclayton@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
980145bc16
commit
13f089095f
@@ -5709,7 +5709,7 @@ bool FunctionEmitter::EmitImageQuery(const spvtools::opt::Instruction& inst) {
|
||||
Source{}, builder_.Symbols().Register("textureDimensions"));
|
||||
ExpressionList dims_args{GetImageExpression(inst)};
|
||||
if (opcode == SpvOpImageQuerySizeLod) {
|
||||
dims_args.Push(ToI32(MakeOperand(inst, 1)).expr);
|
||||
dims_args.Push(MakeOperand(inst, 1).expr);
|
||||
}
|
||||
const ast::Expression* dims_call =
|
||||
create<ast::CallExpression>(Source{}, dims_ident, dims_args);
|
||||
@@ -5724,18 +5724,29 @@ bool FunctionEmitter::EmitImageQuery(const spvtools::opt::Instruction& inst) {
|
||||
if (ast::IsTextureArray(dims)) {
|
||||
auto* layers_ident = create<ast::IdentifierExpression>(
|
||||
Source{}, builder_.Symbols().Register("textureNumLayers"));
|
||||
exprs.Push(create<ast::CallExpression>(Source{}, layers_ident,
|
||||
utils::Vector{GetImageExpression(inst)}));
|
||||
auto num_layers = create<ast::CallExpression>(
|
||||
Source{}, layers_ident, utils::Vector{GetImageExpression(inst)});
|
||||
exprs.Push(num_layers);
|
||||
}
|
||||
auto* result_type = parser_impl_.ConvertType(inst.type_id());
|
||||
auto* unsigned_type = ty_.AsUnsigned(result_type);
|
||||
TypedExpression expr = {
|
||||
result_type,
|
||||
builder_.Construct(Source{}, result_type->Build(builder_), std::move(exprs))};
|
||||
unsigned_type,
|
||||
// If `exprs` holds multiple expressions, then these are the calls to
|
||||
// textureDimensions() and textureNumLayers(), and these need to be placed into a
|
||||
// vector initializer - otherwise, just emit the single expression to omit an
|
||||
// unnecessary cast.
|
||||
(exprs.Length() > 1)
|
||||
? builder_.Construct(Source{}, unsigned_type->Build(builder_), std::move(exprs))
|
||||
: exprs[0],
|
||||
};
|
||||
|
||||
expr = ToSignedIfUnsigned(expr);
|
||||
|
||||
return EmitConstDefOrWriteToHoistedVar(inst, expr);
|
||||
}
|
||||
case SpvOpImageQueryLod:
|
||||
return Fail() << "WGSL does not support querying the level of detail of "
|
||||
"an image: "
|
||||
return Fail() << "WGSL does not support querying the level of detail of an image: "
|
||||
<< inst.PrettyPrint();
|
||||
case SpvOpImageQueryLevels:
|
||||
case SpvOpImageQuerySamples: {
|
||||
@@ -5746,9 +5757,10 @@ bool FunctionEmitter::EmitImageQuery(const spvtools::opt::Instruction& inst) {
|
||||
const ast::Expression* ast_expr = create<ast::CallExpression>(
|
||||
Source{}, levels_ident, utils::Vector{GetImageExpression(inst)});
|
||||
auto* result_type = parser_impl_.ConvertType(inst.type_id());
|
||||
// The SPIR-V result type must be integer scalar. The WGSL bulitin
|
||||
// returns i32. If they aren't the same then convert the result.
|
||||
if (!result_type->Is<I32>()) {
|
||||
// The SPIR-V result type must be integer scalar.
|
||||
// The WGSL bulitin returns u32.
|
||||
// If they aren't the same then convert the result.
|
||||
if (!result_type->Is<U32>()) {
|
||||
ast_expr = builder_.Construct(Source{}, result_type->Build(builder_),
|
||||
utils::Vector{ast_expr});
|
||||
}
|
||||
|
||||
@@ -956,17 +956,15 @@ class FunctionEmitter {
|
||||
ExpressionList MakeCoordinateOperandsForImageAccess(
|
||||
const spvtools::opt::Instruction& image_access);
|
||||
|
||||
/// Returns the given value as an I32. If it's already an I32 then this
|
||||
/// return the given value. Otherwise, wrap the value in a TypeInitializer
|
||||
/// expression.
|
||||
/// Returns the given value as an i32. If it's already an i32 then simply returns @p value.
|
||||
/// Otherwise, wrap the value in a TypeInitializer expression.
|
||||
/// @param value the value to pass through or convert
|
||||
/// @returns the value as an I32 value.
|
||||
/// @returns the value as an i32 value.
|
||||
TypedExpression ToI32(TypedExpression value);
|
||||
|
||||
/// Returns the given value as a signed integer type of the same shape
|
||||
/// if the value is unsigned scalar or vector, by wrapping the value
|
||||
/// with a TypeInitializer expression. Returns the value itself if the
|
||||
/// value otherwise.
|
||||
/// Returns the given value as a signed integer type of the same shape if the value is unsigned
|
||||
/// scalar or vector, by wrapping the value with a TypeInitializer expression. Returns the
|
||||
/// value itself if the value was already signed.
|
||||
/// @param value the value to pass through or convert
|
||||
/// @returns the value itself, or converted to signed integral
|
||||
TypedExpression ToSignedIfUnsigned(TypedExpression value);
|
||||
|
||||
@@ -2842,7 +2842,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
"%99 = OpImageQuerySize %v3int %im \n"
|
||||
"%98 = OpImageRead %v4float %im %vi123\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_2d_array<f32>;)",
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(textureDimensions(x_20), textureNumLayers(x_20));)"}
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(vec3<u32>(textureDimensions(x_20), textureNumLayers(x_20)));)"}
|
||||
// 3D array storage image doesn't exist.
|
||||
|
||||
// Multisampled array
|
||||
@@ -2898,7 +2898,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
// 2D array
|
||||
{"%float 2D 0 1 0 1 Unknown", "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_2d_array<f32>;)",
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(textureDimensions(x_20, i1), textureNumLayers(x_20));)"},
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(vec3<u32>(textureDimensions(x_20, i1), textureNumLayers(x_20)));)"},
|
||||
|
||||
// There is no 3D array
|
||||
|
||||
@@ -2909,12 +2909,12 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
// https://github.com/gpuweb/gpuweb/issues/1345
|
||||
{"%float Cube 0 1 0 1 Unknown", "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_cube_array<f32>;)",
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(textureDimensions(x_20, i1).xy, textureNumLayers(x_20));)"},
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(vec3<u32>(textureDimensions(x_20, i1).xy, textureNumLayers(x_20)));)"},
|
||||
|
||||
// Depth 2D array
|
||||
{"%float 2D 1 1 0 1 Unknown", "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(textureDimensions(x_20, i1), textureNumLayers(x_20));)"},
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(vec3<u32>(textureDimensions(x_20, i1), textureNumLayers(x_20)));)"},
|
||||
|
||||
// Depth Cube Array
|
||||
//
|
||||
@@ -2923,19 +2923,17 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
// https://github.com/gpuweb/gpuweb/issues/1345
|
||||
{"%float Cube 1 1 0 1 Unknown", "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_depth_cube_array;)",
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(textureDimensions(x_20, i1).xy, textureNumLayers(x_20));)"}}));
|
||||
R"(let x_99 : vec3<i32> = vec3<i32>(vec3<u32>(textureDimensions(x_20, i1).xy, textureNumLayers(x_20)));)"}}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
// When the level-of-detail value is given as an unsigned
|
||||
// integer, we must convert it before using it as an argument
|
||||
// to textureDimensions.
|
||||
// textureDimensions accepts both signed and unsigned the level-of-detail values.
|
||||
ImageQuerySizeLod_NonArrayed_SignedResult_UnsignedLevel,
|
||||
SpvParserHandleTest_SampledImageAccessTest,
|
||||
::testing::ValuesIn(std::vector<ImageAccessCase>{
|
||||
|
||||
{"%float 1D 0 0 0 1 Unknown", "%99 = OpImageQuerySizeLod %int %im %u1\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_1d<f32>;)",
|
||||
R"(let x_99 : i32 = i32(textureDimensions(x_20, i32(u1)));)"}}));
|
||||
R"(let x_99 : i32 = i32(textureDimensions(x_20, u1));)"}}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
// When SPIR-V wants the result type to be unsigned, we have to
|
||||
@@ -2948,7 +2946,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
|
||||
{"%float 1D 0 0 0 1 Unknown", "%99 = OpImageQuerySizeLod %uint %im %i1\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_1d<f32>;)",
|
||||
R"(let x_99 : u32 = u32(textureDimensions(x_20, i1));)"}}));
|
||||
R"(let x_99 : i32 = i32(textureDimensions(x_20, i1));)"}}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ImageQueryLevels_SignedResult,
|
||||
SpvParserHandleTest_SampledImageAccessTest,
|
||||
@@ -2961,47 +2959,47 @@ INSTANTIATE_TEST_SUITE_P(ImageQueryLevels_SignedResult,
|
||||
// 2D
|
||||
{"%float 2D 0 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_2d<f32>;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"},
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"},
|
||||
|
||||
// 2D array
|
||||
{"%float 2D 0 1 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_2d_array<f32>;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"},
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"},
|
||||
|
||||
// 3D
|
||||
{"%float 3D 0 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_3d<f32>;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"},
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"},
|
||||
|
||||
// Cube
|
||||
{"%float Cube 0 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_cube<f32>;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"},
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"},
|
||||
|
||||
// Cube array
|
||||
{"%float Cube 0 1 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_cube_array<f32>;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"},
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"},
|
||||
|
||||
// depth 2d
|
||||
{"%float 2D 1 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_depth_2d;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"},
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"},
|
||||
|
||||
// depth 2d array
|
||||
{"%float 2D 1 1 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"},
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"},
|
||||
|
||||
// depth cube
|
||||
{"%float Cube 1 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_depth_cube;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"},
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"},
|
||||
|
||||
// depth cube array
|
||||
{"%float Cube 1 1 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_depth_cube_array;)",
|
||||
R"(let x_99 : i32 = textureNumLevels(x_20);)"}}));
|
||||
R"(let x_99 : i32 = i32(textureNumLevels(x_20));)"}}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
// Spot check that a type conversion is inserted when SPIR-V asks for
|
||||
@@ -3011,7 +3009,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
::testing::ValuesIn(std::vector<ImageAccessCase>{
|
||||
{"%float 2D 0 0 0 1 Unknown", "%99 = OpImageQueryLevels %uint %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_2d<f32>;)",
|
||||
R"(let x_99 : u32 = u32(textureNumLevels(x_20));)"}}));
|
||||
R"(let x_99 : u32 = textureNumLevels(x_20);)"}}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ImageQuerySamples_SignedResult,
|
||||
SpvParserHandleTest_SampledImageAccessTest,
|
||||
@@ -3019,21 +3017,21 @@ INSTANTIATE_TEST_SUITE_P(ImageQuerySamples_SignedResult,
|
||||
// Multsample 2D
|
||||
{"%float 2D 0 0 1 1 Unknown", "%99 = OpImageQuerySamples %int %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_multisampled_2d<f32>;)",
|
||||
R"(let x_99 : i32 = textureNumSamples(x_20);)"} // namespace
|
||||
R"(let x_99 : i32 = i32(textureNumSamples(x_20));)"}
|
||||
|
||||
// Multisample 2D array
|
||||
// Not in WebGPU
|
||||
}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
// Translation must inject a type coersion from signed to unsigned.
|
||||
// Translation must inject a type coersion from unsigned to signed.
|
||||
ImageQuerySamples_UnsignedResult,
|
||||
SpvParserHandleTest_SampledImageAccessTest,
|
||||
::testing::ValuesIn(std::vector<ImageAccessCase>{
|
||||
// Multsample 2D
|
||||
// Multisample 2D
|
||||
{"%float 2D 0 0 1 1 Unknown", "%99 = OpImageQuerySamples %uint %im\n",
|
||||
R"(@group(2) @binding(1) var x_20 : texture_multisampled_2d<f32>;)",
|
||||
R"(let x_99 : u32 = u32(textureNumSamples(x_20));)"}
|
||||
R"(let x_99 : u32 = textureNumSamples(x_20);)"}
|
||||
|
||||
// Multisample 2D array
|
||||
// Not in WebGPU
|
||||
|
||||
@@ -444,6 +444,20 @@ const spirv::I32* TypeManager::I32() {
|
||||
return state->i32_;
|
||||
}
|
||||
|
||||
const Type* TypeManager::AsUnsigned(const Type* ty) {
|
||||
return Switch(
|
||||
ty, //
|
||||
[&](const spirv::I32*) { return U32(); }, //
|
||||
[&](const spirv::U32*) { return ty; }, //
|
||||
[&](const spirv::Vector* vec) {
|
||||
return Switch(
|
||||
vec->type, //
|
||||
[&](const spirv::I32*) { return Vector(U32(), vec->size); }, //
|
||||
[&](const spirv::U32*) { return ty; } //
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const spirv::Pointer* TypeManager::Pointer(const Type* el,
|
||||
ast::AddressSpace address_space,
|
||||
ast::Access access) {
|
||||
|
||||
@@ -539,6 +539,11 @@ class TypeManager {
|
||||
const spirv::F32* F32();
|
||||
/// @return a I32 type. Repeated calls will return the same pointer.
|
||||
const spirv::I32* I32();
|
||||
/// @param ty the input type.
|
||||
/// @returns the equivalent unsigned integer scalar or vector if @p ty is a scalar or vector,
|
||||
/// otherwise nullptr.
|
||||
const Type* AsUnsigned(const Type* ty);
|
||||
|
||||
/// @param ty the store type
|
||||
/// @param address_space the pointer address space
|
||||
/// @param access the declared access mode
|
||||
|
||||
Reference in New Issue
Block a user