1717 * limitations under the License.
1818 */
1919
20+ #include < vulkan/vk_enum_string_helper.h>
2021#include " drawdispatch/drawdispatch_vuids.h"
2122#include " core_validation.h"
2223#include " generated/vk_extension_helper.h"
2728#include " state_tracker/shader_module.h"
2829#include " state_tracker/cmd_buffer_state.h"
2930#include " state_tracker/pipeline_state.h"
31+ #include " utils/vk_layer_utils.h"
3032
3133using vvl::DrawDispatchVuid;
3234using vvl::GetDrawDispatchVuid;
@@ -1374,12 +1376,26 @@ bool CoreChecks::ValidateActionStateDescriptorsPipeline(const LastBound &last_bo
13741376 }
13751377
13761378 // Check if the current pipeline is compatible for the maximum used set with the bound sets.
1377- if (pipeline.descriptor_buffer_mode ) return skip;
1379+ if (pipeline.descriptor_buffer_mode ) {
1380+ return skip;
1381+ }
13781382
13791383 const auto pipeline_layout = pipeline.PipelineLayoutState ();
13801384 if (!pipeline.active_slots .empty () && !last_bound_state.IsBoundSetCompatible (pipeline.max_active_slot , *pipeline_layout)) {
1385+ // If they never bound any descriptors
1386+ if (!last_bound_state.desc_set_pipeline_layout ) {
1387+ skip |= LogError (vuid.compatible_pipeline_08600 , cb_state.GetObjectList (bind_point), vuid.loc (),
1388+ " The %s statically uses descriptor set %" PRIu32
1389+ " , but because a descriptor was never bound, the pipeline layouts are not compatible.\n If using a "
1390+ " descriptor, make sure to call one of vkCmdBindDescriptorSets, vkCmdPushDescriptorSet, "
1391+ " vkCmdSetDescriptorBufferOffset, etc for %s" ,
1392+ FormatHandle (pipeline).c_str (), pipeline.max_active_slot , string_VkPipelineBindPoint (bind_point));
1393+ return skip;
1394+ }
1395+
13811396 LogObjectList objlist (pipeline.Handle ());
13821397 const auto layouts = pipeline.PipelineLayoutStateUnion ();
1398+ // GPL can have multiple pipeline layouts used to build up a single valid compatible set
13831399 std::ostringstream pipe_layouts_log;
13841400 if (layouts.size () > 1 ) {
13851401 pipe_layouts_log << " a union of layouts [ " ;
@@ -1391,21 +1407,17 @@ bool CoreChecks::ValidateActionStateDescriptorsPipeline(const LastBound &last_bo
13911407 } else {
13921408 pipe_layouts_log << FormatHandle (*layouts.front ());
13931409 }
1394- std::string pipeline_layout_handle_str;
1395- if (last_bound_state.desc_set_pipeline_layout ) {
1396- pipeline_layout_handle_str = FormatHandle (last_bound_state.desc_set_pipeline_layout ->Handle ());
1397- objlist.add (last_bound_state.desc_set_pipeline_layout ->Handle ());
1398- } else {
1399- pipeline_layout_handle_str = " Pipeline Layout never bound" ; // < can happen when dealing with multiview
1400- }
1410+
1411+ objlist.add (last_bound_state.desc_set_pipeline_layout ->Handle ());
14011412
14021413 std::string range =
14031414 pipeline.max_active_slot == 0 ? " set 0 is" : " all sets 0 to " + std::to_string (pipeline.max_active_slot ) + " are" ;
14041415 skip |= LogError (vuid.compatible_pipeline_08600 , objlist, vuid.loc (),
14051416 " The %s (created with %s) statically uses descriptor set %" PRIu32
14061417 " , but %s not compatible with the pipeline layout bound with %s (%s)\n %s" ,
14071418 FormatHandle (pipeline).c_str (), pipe_layouts_log.str ().c_str (), pipeline.max_active_slot , range.c_str (),
1408- String (last_bound_state.desc_set_bound_command ), pipeline_layout_handle_str.c_str (),
1419+ String (last_bound_state.desc_set_bound_command ),
1420+ FormatHandle (last_bound_state.desc_set_pipeline_layout ->Handle ()).c_str (),
14091421 last_bound_state.DescribeNonCompatibleSet (pipeline.max_active_slot , *pipeline_layout).c_str ());
14101422 } else {
14111423 // if the bound set is not compatible, the rest will just be extra redundant errors
@@ -1414,17 +1426,16 @@ bool CoreChecks::ValidateActionStateDescriptorsPipeline(const LastBound &last_bo
14141426 const auto ds_slot = last_bound_state.ds_slots [set_index];
14151427 if (!ds_slot.ds_state ) {
14161428 skip |= LogError (vuid.compatible_pipeline_08600 , cb_state.GetObjectList (bind_point), vuid.loc (),
1417- " %s uses set # %" PRIu32
1429+ " %s uses set %" PRIu32
14181430 " but that set is not bound. (Need to use a command like vkCmdBindDescriptorSets to bind the set)" ,
14191431 FormatHandle (pipeline).c_str (), set_index);
1420- } else if (!VerifySetLayoutCompatibility (*ds_slot.ds_state , pipeline_layout->set_layouts , pipeline_layout-> Handle () ,
1421- set_index, error_string)) {
1422- // Set is bound but not compatible w/ overlapping pipeline_layout from PSO
1432+ } else if (!VerifyDescriptorSetIsCompatibile (*ds_slot.ds_state , pipeline_layout->set_layouts , set_index ,
1433+ error_string)) {
1434+ // Set is bound but not compatible w/ corresponding VkPipelineLayoutCreateInfo::pSetLayouts
14231435 VkDescriptorSet set_handle = ds_slot.ds_state ->VkHandle ();
1424- LogObjectList objlist = cb_state.GetObjectList (bind_point);
1425- objlist.add (set_handle);
1436+ const LogObjectList objlist (cb_state.Handle (), set_handle, pipeline.Handle (), pipeline_layout->Handle ());
14261437 skip |= LogError (vuid.compatible_pipeline_08600 , objlist, vuid.loc (),
1427- " %s bound as set # %" PRIu32 " is not compatible with overlapping %s due to: %s" ,
1438+ " %s bound as set %" PRIu32 " is not compatible with corresponding %s\n %s" ,
14281439 FormatHandle (set_handle).c_str (), set_index, FormatHandle (*pipeline_layout).c_str (),
14291440 error_string.c_str ());
14301441 } else { // Valid set is bound and layout compatible, validate that it's updated
@@ -1450,16 +1461,37 @@ bool CoreChecks::ValidateActionStateDescriptorsShaderObject(const LastBound &las
14501461
14511462 // Check if the current shader objects are compatible for the maximum used set with the bound sets.
14521463 for (const auto &shader_state : last_bound_state.shader_object_states ) {
1453- if (!shader_state) continue ;
1464+ if (!shader_state) {
1465+ continue ;
1466+ }
14541467
1455- if (shader_state && !shader_state->active_slots .empty () &&
1468+ if (!shader_state->active_slots .empty () &&
14561469 !last_bound_state.IsBoundSetCompatible (shader_state->max_active_slot , *shader_state)) {
14571470 LogObjectList objlist (cb_state.Handle (), shader_state->Handle ());
1458- skip |= LogError (vuid.compatible_pipeline_08600 , objlist, vuid.loc (),
1459- " The %s statically uses descriptor set (index #%" PRIu32
1460- " ) which is not compatible with the currently bound descriptor set's layout\n %s" ,
1461- FormatHandle (shader_state->Handle ()).c_str (), shader_state->max_active_slot ,
1462- last_bound_state.DescribeNonCompatibleSet (shader_state->max_active_slot , *shader_state).c_str ());
1471+
1472+ if (!last_bound_state.desc_set_pipeline_layout ) {
1473+ // If they never bound any descriptors
1474+ skip |= LogError (vuid.compatible_pipeline_08600 , cb_state.GetObjectList (bind_point), vuid.loc (),
1475+ " The %s statically uses descriptor set %" PRIu32
1476+ " , but because a descriptor was never bound, the pipeline layouts are not compatible.\n If using "
1477+ " a descriptor, make sure to call one of vkCmdBindDescriptorSets, vkCmdPushDescriptorSet, "
1478+ " vkCmdSetDescriptorBufferOffset, etc for %s" ,
1479+ FormatHandle (shader_state->Handle ()).c_str (), shader_state->max_active_slot ,
1480+ string_VkPipelineBindPoint (bind_point));
1481+
1482+ } else {
1483+ objlist.add (last_bound_state.desc_set_pipeline_layout ->Handle ());
1484+ std::string range = shader_state->max_active_slot == 0
1485+ ? " set 0 is"
1486+ : " all sets 0 to " + std::to_string (shader_state->max_active_slot ) + " are" ;
1487+ skip |= LogError (vuid.compatible_pipeline_08600 , objlist, vuid.loc (),
1488+ " The %s statically uses descriptor set %" PRIu32
1489+ " but %s not compatible with the pipeline layout bound with %s (%s)\n %s" ,
1490+ FormatHandle (shader_state->Handle ()).c_str (), shader_state->max_active_slot , range.c_str (),
1491+ String (last_bound_state.desc_set_bound_command ),
1492+ FormatHandle (last_bound_state.desc_set_pipeline_layout ->Handle ()).c_str (),
1493+ last_bound_state.DescribeNonCompatibleSet (shader_state->max_active_slot , *shader_state).c_str ());
1494+ }
14631495 } else {
14641496 // if the bound set is not copmatible, the rest will just be extra redundant errors
14651497 for (const auto &[set_index, binding_req_map] : shader_state->active_slots ) {
@@ -1468,15 +1500,15 @@ bool CoreChecks::ValidateActionStateDescriptorsShaderObject(const LastBound &las
14681500 if (!ds_slot.ds_state ) {
14691501 const LogObjectList objlist (cb_state.Handle (), shader_state->Handle ());
14701502 skip |= LogError (vuid.compatible_pipeline_08600 , objlist, vuid.loc (),
1471- " %s uses set # %" PRIu32 " but that set is not bound." ,
1503+ " %s uses set %" PRIu32 " but that set is not bound." ,
14721504 FormatHandle (shader_state->Handle ()).c_str (), set_index);
1473- } else if (!VerifySetLayoutCompatibility (*ds_slot.ds_state , shader_state->set_layouts , shader_state-> Handle () ,
1474- set_index, error_string)) {
1475- // Set is bound but not compatible w/ overlapping pipeline_layout from PSO
1505+ } else if (!VerifyDescriptorSetIsCompatibile (*ds_slot.ds_state , shader_state->set_layouts , set_index ,
1506+ error_string)) {
1507+ // Set is bound but not compatible w/ corresponding VkShaderCreateInfoEXT::pSetLayouts
14761508 VkDescriptorSet set_handle = ds_slot.ds_state ->VkHandle ();
14771509 const LogObjectList objlist (cb_state.Handle (), set_handle, shader_state->Handle ());
14781510 skip |= LogError (vuid.compatible_pipeline_08600 , objlist, vuid.loc (),
1479- " %s bound as set # %" PRIu32 " is not compatible with overlapping %s due to: %s" ,
1511+ " %s bound as set %" PRIu32 " is not compatible with corresponding %s\n %s" ,
14801512 FormatHandle (set_handle).c_str (), set_index, FormatHandle (shader_state->Handle ()).c_str (),
14811513 error_string.c_str ());
14821514 } else { // Valid set is bound and layout compatible, validate that it's updated
0 commit comments