diff options
author | Jason Ekstrand <[email protected]> | 2018-01-02 07:45:42 -0800 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2018-01-08 14:57:44 -0800 |
commit | 70f588778c828aeb33277d35140f57d8fbeaca4a (patch) | |
tree | 0edbc891e94edb95ee0519b6922b04b8cbfae1e0 /src/compiler | |
parent | 8bad7f33c661eb0ec10d54b6297ed537822a4c78 (diff) |
spirv: Add a vtn_types_compatible helper
Tested-by: Eero Tamminen <[email protected]>
Reviewed-by: Lionel Landwerlin <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/spirv/spirv_to_nir.c | 52 | ||||
-rw-r--r-- | src/compiler/spirv/vtn_private.h | 3 |
2 files changed, 55 insertions, 0 deletions
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 09aea54ed39..c6df764682e 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -537,6 +537,58 @@ struct member_decoration_ctx { struct vtn_type *type; }; +/** Returns true if two types are "compatible", i.e. you can do an OpLoad, + * OpStore, or OpCopyMemory between them without breaking anything. + * Technically, the SPIR-V rules require the exact same type ID but this lets + * us internally be a bit looser. + */ +bool +vtn_types_compatible(struct vtn_builder *b, + struct vtn_type *t1, struct vtn_type *t2) +{ + if (t1->id == t2->id) + return true; + + if (t1->base_type != t2->base_type) + return false; + + switch (t1->base_type) { + case vtn_base_type_void: + case vtn_base_type_scalar: + case vtn_base_type_vector: + case vtn_base_type_matrix: + case vtn_base_type_image: + case vtn_base_type_sampler: + case vtn_base_type_sampled_image: + return t1->type == t2->type; + + case vtn_base_type_array: + return t1->length == t2->length && + vtn_types_compatible(b, t1->array_element, t2->array_element); + + case vtn_base_type_pointer: + return vtn_types_compatible(b, t1->deref, t2->deref); + + case vtn_base_type_struct: + if (t1->length != t2->length) + return false; + + for (unsigned i = 0; i < t1->length; i++) { + if (!vtn_types_compatible(b, t1->members[i], t2->members[i])) + return false; + } + return true; + + case vtn_base_type_function: + /* This case shouldn't get hit since you can't copy around function + * types. Just require them to be identical. + */ + return false; + } + + vtn_fail("Invalid base type"); +} + /* does a shallow copy of a vtn_type */ static struct vtn_type * diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index f27ef8e3eff..3e49df4dac8 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -365,6 +365,9 @@ struct vtn_type { }; }; +bool vtn_types_compatible(struct vtn_builder *b, + struct vtn_type *t1, struct vtn_type *t2); + struct vtn_variable; enum vtn_access_mode { |