Skip to content

Commit

Permalink
[WGSL] shader,validation,decl,var:* is failing
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=268878
rdar://122436149

Reviewed by Mike Wyrzykowski.

Validate the type of variable declarations according to the spec rules[1] based
on the address space and access mode.

[1]: https://www.w3.org/TR/WGSL/#var-and-value

* Source/WebGPU/WGSL/TypeCheck.cpp:
(WGSL::TypeChecker::visitVariable):
* Source/WebGPU/WGSL/Types.cpp:
(WGSL::Type::isStorable const):
(WGSL::Type::isHostShareable const):
(WGSL::Type::hasFixedFootprint const):
* Source/WebGPU/WGSL/Types.h:

Canonical link: https://commits.webkit.org/274243@main
  • Loading branch information
tadeuzagallo committed Feb 7, 2024
1 parent 446cdce commit 200045f
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 10 deletions.
50 changes: 40 additions & 10 deletions Source/WebGPU/WGSL/TypeCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,26 +502,56 @@ void TypeChecker::visitVariable(AST::Variable& variable, VariableKind variableKi
variable.m_addressSpace = addressSpace;
variable.m_accessMode = accessMode;

if (addressSpace == AddressSpace::Function && variableKind == VariableKind::Global)
return error("module-scope 'var' must not use address space 'function'");
if ((addressSpace == AddressSpace::Storage || addressSpace == AddressSpace::Uniform || addressSpace == AddressSpace::Handle || addressSpace == AddressSpace::Workgroup) && variable.maybeInitializer())
return error("variables in the address space '", toString(addressSpace), "' cannot have an initializer");
if (addressSpace == AddressSpace::Storage && accessMode == AccessMode::Write)
return error("access mode 'write' is not valid for the <storage> address space");
if (addressSpace == AddressSpace::Handle) {
// https://www.w3.org/TR/WGSL/#var-and-value
switch (addressSpace) {
case AddressSpace::Storage:
if (accessMode == AccessMode::Write)
return error("access mode 'write' is not valid for the <storage> address space");
if (!result->isHostShareable())
return error("type '", *result, "' cannot be used in address space <storage> because it's not host-shareable");
if (accessMode == AccessMode::Read && std::holds_alternative<Types::Atomic>(*result))
return error("atomic variables in <storage> address space must have read_write access mode");
break;
case AddressSpace::Uniform:
if (!result->isHostShareable())
return error("type '", *result, "' cannot be used in address space <uniform> because it's not host-shareable");
if (!result->isConstructible())
return error("type '", *result, "' cannot be used in address space <uniform> because it's not constructible");
break;
case AddressSpace::Workgroup:
if (!result->hasFixedFootprint())
return error("type '", *result, "' cannot be used in address space <workgroup> because it doesn't have fixed footprint");
break;
case AddressSpace::Function:
if (!result->isConstructible())
return error("type '", *result, "' cannot be used in address space <function> because it's not constructible");
break;
case AddressSpace::Private:
if (!result->isConstructible())
return error("type '", *result, "' cannot be used in address space <private> because it's not constructible");
break;
case AddressSpace::Handle: {
auto* primitive = std::get_if<Types::Primitive>(result);
bool isTypeAllowed = std::holds_alternative<Types::Texture>(*result)
bool isTextureOrSampler = std::holds_alternative<Types::Texture>(*result)
|| std::holds_alternative<Types::TextureStorage>(*result)
|| std::holds_alternative<Types::TextureDepth>(*result)
|| (primitive && (
primitive->kind == Types::Primitive::TextureExternal
|| primitive->kind == Types::Primitive::Sampler
|| primitive->kind == Types::Primitive::SamplerComparison
));
if (!isTypeAllowed)
if (!isTextureOrSampler)
return error("module-scope 'var' declarations that are not of texture or sampler types must provide an address space");
break;
}
break;
}

if (addressSpace == AddressSpace::Function && variableKind == VariableKind::Global)
return error("module-scope 'var' must not use address space 'function'");
if (addressSpace != AddressSpace::Function && variableKind == VariableKind::Local)
return error("function-scope 'var' declaration must use 'function' address space");
if ((addressSpace == AddressSpace::Storage || addressSpace == AddressSpace::Uniform || addressSpace == AddressSpace::Handle || addressSpace == AddressSpace::Workgroup) && variable.maybeInitializer())
return error("variables in the address space '", toString(addressSpace), "' cannot have an initializer");
}

if (value && !isBottom(result))
Expand Down
146 changes: 146 additions & 0 deletions Source/WebGPU/WGSL/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,152 @@ bool Type::isStorable() const
});
}

// https://www.w3.org/TR/WGSL/#host-shareable-types
bool Type::isHostShareable() const
{
return WTF::switchOn(*this,
[&](const Primitive& primitive) -> bool {
switch (primitive.kind) {
case Types::Primitive::F16:
case Types::Primitive::F32:
case Types::Primitive::I32:
case Types::Primitive::U32:
return true;
case Types::Primitive::Bool:
case Types::Primitive::Sampler:
case Types::Primitive::SamplerComparison:
case Types::Primitive::TextureExternal:
case Types::Primitive::AbstractInt:
case Types::Primitive::AbstractFloat:
case Types::Primitive::Void:
case Types::Primitive::AccessMode:
case Types::Primitive::TexelFormat:
case Types::Primitive::AddressSpace:
return false;
}
},
[&](const Vector& vector) -> bool {
return vector.element->isHostShareable();
},
[&](const Matrix& matrix) -> bool {
return matrix.element->isHostShareable();
},
[&](const Array& array) -> bool {
return array.element->isHostShareable();
},
[&](const Struct& structure) -> bool {
for (auto& member : structure.structure.members()) {
if (!member.type().inferredType()->isHostShareable())
return false;
}
return true;
},
[&](const Atomic&) -> bool {
return true;
},

[&](const TextureStorage&) -> bool {
return false;
},
[&](const TextureDepth&) -> bool {
return false;
},
[&](const PrimitiveStruct&) -> bool {
return false;
},
[&](const Function&) -> bool {
return false;
},
[&](const Texture&) -> bool {
return false;
},
[&](const TypeConstructor&) -> bool {
return false;
},
[&](const Reference&) -> bool {
return false;
},
[&](const Pointer&) -> bool {
return false;
},
[&](const Bottom&) -> bool {
return false;
});
}

// https://www.w3.org/TR/WGSL/#fixed-footprint
bool Type::hasFixedFootprint() const
{
return WTF::switchOn(*this,
[&](const Primitive& primitive) -> bool {
switch (primitive.kind) {
case Types::Primitive::F16:
case Types::Primitive::F32:
case Types::Primitive::I32:
case Types::Primitive::U32:
case Types::Primitive::Bool:
return true;
case Types::Primitive::Sampler:
case Types::Primitive::SamplerComparison:
case Types::Primitive::TextureExternal:
case Types::Primitive::AbstractInt:
case Types::Primitive::AbstractFloat:
case Types::Primitive::Void:
case Types::Primitive::AccessMode:
case Types::Primitive::TexelFormat:
case Types::Primitive::AddressSpace:
return false;
}
},
[&](const Vector&) -> bool {
return true;
},
[&](const Matrix&) -> bool {
return true;
},
[&](const Array& array) -> bool {
return array.size.has_value();
},
[&](const Struct& structure) -> bool {
for (auto& member : structure.structure.members()) {
if (!member.type().inferredType()->hasFixedFootprint())
return false;
}
return true;
},
[&](const Atomic&) -> bool {
return true;
},

[&](const TextureStorage&) -> bool {
return false;
},
[&](const TextureDepth&) -> bool {
return false;
},
[&](const PrimitiveStruct&) -> bool {
return false;
},
[&](const Function&) -> bool {
return false;
},
[&](const Texture&) -> bool {
return false;
},
[&](const TypeConstructor&) -> bool {
return false;
},
[&](const Reference&) -> bool {
return false;
},
[&](const Pointer&) -> bool {
return false;
},
[&](const Bottom&) -> bool {
return false;
});
}

bool Type::containsRuntimeArray() const
{
if (auto* array = std::get_if<Types::Array>(this))
Expand Down
2 changes: 2 additions & 0 deletions Source/WebGPU/WGSL/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ struct Type : public std::variant<
Packing packing() const;
bool isConstructible() const;
bool isStorable() const;
bool isHostShareable() const;
bool hasFixedFootprint() const;
bool containsRuntimeArray() const;
};

Expand Down

0 comments on commit 200045f

Please sign in to comment.