From ebea572a9be80101c2aedad11928039d12cc98e2 Mon Sep 17 00:00:00 2001 From: Chris Forbes <chrisforbes@google.com> Date: Tue, 29 Mar 2016 16:38:44 +1300 Subject: [PATCH] layers: Rework array-of-verts stripping a bit to support patch Signed-off-by: Chris Forbes <chrisforbes@google.com> --- layers/core_validation.cpp | 47 ++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index ec4d76a9..b6fcaf83 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -1245,67 +1245,70 @@ static std::string describe_type(shader_module const *src, unsigned type) { } -static bool types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool b_arrayed) { +static bool types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool a_arrayed, bool b_arrayed) { /* walk two type trees together, and complain about differences */ auto a_insn = a->get_def(a_type); auto b_insn = b->get_def(b_type); assert(a_insn != a->end()); assert(b_insn != b->end()); + if (a_arrayed && a_insn.opcode() == spv::OpTypeArray) { + return types_match(a, b, a_insn.word(2), b_type, false, b_arrayed); + } + if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) { /* we probably just found the extra level of arrayness in b_type: compare the type inside it to a_type */ - return types_match(a, b, a_type, b_insn.word(2), false); + return types_match(a, b, a_type, b_insn.word(2), a_arrayed, false); } if (a_insn.opcode() != b_insn.opcode()) { return false; } + if (a_insn.opcode() == spv::OpTypePointer) { + /* match on pointee type. storage class is expected to differ */ + return types_match(a, b, a_insn.word(3), b_insn.word(3), a_arrayed, b_arrayed); + } + + if (a_arrayed || b_arrayed) { + /* if we havent resolved array-of-verts by here, we're not going to. */ + return false; + } + switch (a_insn.opcode()) { - /* if b_arrayed and we hit a leaf type, then we can't match -- there's nowhere for the extra OpTypeArray to be! */ case spv::OpTypeBool: - return true && !b_arrayed; + return true; case spv::OpTypeInt: /* match on width, signedness */ - return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3) && !b_arrayed; + return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3); case spv::OpTypeFloat: /* match on width */ - return a_insn.word(2) == b_insn.word(2) && !b_arrayed; + return a_insn.word(2) == b_insn.word(2); case spv::OpTypeVector: case spv::OpTypeMatrix: - /* match on element type, count. these all have the same layout. we don't get here if - * b_arrayed -- that is handled above. */ - return !b_arrayed && types_match(a, b, a_insn.word(2), b_insn.word(2), b_arrayed) && a_insn.word(3) == b_insn.word(3); + /* match on element type, count. these all have the same layout. */ + return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed) && a_insn.word(3) == b_insn.word(3); case spv::OpTypeArray: /* match on element type, count. these all have the same layout. we don't get here if * b_arrayed. This differs from vector & matrix types in that the array size is the id of a constant instruction, * not a literal within OpTypeArray */ - return !b_arrayed && types_match(a, b, a_insn.word(2), b_insn.word(2), b_arrayed) && + return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed) && get_constant_value(a, a_insn.word(3)) == get_constant_value(b, b_insn.word(3)); case spv::OpTypeStruct: /* match on all element types */ { - if (b_arrayed) { - /* for the purposes of matching different levels of arrayness, structs are leaves. */ - return false; - } - if (a_insn.len() != b_insn.len()) { return false; /* structs cannot match if member counts differ */ } for (unsigned i = 2; i < a_insn.len(); i++) { - if (!types_match(a, b, a_insn.word(i), b_insn.word(i), b_arrayed)) { + if (!types_match(a, b, a_insn.word(i), b_insn.word(i), a_arrayed, b_arrayed)) { return false; } } return true; } - case spv::OpTypePointer: - /* match on pointee type. storage class is expected to differ */ - return types_match(a, b, a_insn.word(3), b_insn.word(3), b_arrayed); - default: /* remaining types are CLisms, or may not appear in the interfaces we * are interested in. Just claim no match. @@ -1502,7 +1505,7 @@ static void collect_interface_by_location(layer_data *my_data, shader_module con if (location != -1) { /* A user-defined interface variable, with a location. Where a variable * occupied multiple locations, emit one result for each. */ - unsigned num_locations = get_locations_consumed_by_type(src, type, is_array_of_verts); + unsigned num_locations = get_locations_consumed_by_type(src, type, is_array_of_verts && !is_patch); for (unsigned int offset = 0; offset < num_locations; offset++) { interface_var v; v.id = id; @@ -1610,7 +1613,7 @@ static bool validate_interface_between_stages(layer_data *my_data, shader_module } b_it++; } else { - if (types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, consumer_arrayed_input)) { + if (types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, false, consumer_arrayed_input)) { /* OK! */ } else { if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, -- 2.34.1