@@ -2325,16 +2325,12 @@ bool CoreChecks::ValidateCmdSetDescriptorBufferOffsets(const vvl::CommandBuffer
23252325 skip |= ValidateCmd (cb_state, loc);
23262326
23272327 auto pipeline_layout = Get<vvl::PipelineLayout>(layout);
2328- if (!pipeline_layout) return skip; // dynamicPipelineLayout
2328+ if (!pipeline_layout) {
2329+ return skip; // dynamicPipelineLayout
2330+ }
23292331
23302332 const bool is_2 = loc.function != Func::vkCmdSetDescriptorBufferOffsetsEXT;
23312333
2332- if (!enabled_features.descriptorBuffer ) {
2333- const char *vuid = is_2 ? " VUID-vkCmdSetDescriptorBufferOffsets2EXT-descriptorBuffer-09470"
2334- : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-None-08060" ;
2335- skip |= LogError (vuid, cb_state.Handle (), loc, " descriptorBuffer feature was not enabled." );
2336- }
2337-
23382334 if ((firstSet + setCount) > pipeline_layout->set_layouts .size ()) {
23392335 const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-firstSet-08066"
23402336 : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-firstSet-08066" ;
@@ -2347,6 +2343,17 @@ bool CoreChecks::ValidateCmdSetDescriptorBufferOffsets(const vvl::CommandBuffer
23472343 setCount = std::min (setCount, static_cast <uint32_t >(pipeline_layout->set_layouts .size ()));
23482344 }
23492345
2346+ if (cb_state.descriptor_buffer_binding_info .empty ()) {
2347+ const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-pBufferIndices-08065"
2348+ : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-pBufferIndices-08065" ;
2349+ const LogObjectList objlist (cb_state.Handle (), pipeline_layout->Handle ());
2350+ skip |= LogError (vuid, objlist, loc,
2351+ " There have been no calls to vkCmdBindDescriptorBuffersEXT and no descriptor buffers are bound. Any "
2352+ " future call will vkCmdBindDescriptorBuffersEXT would invalidate these offsets anyway." );
2353+ // everything else won't make sense
2354+ return skip;
2355+ }
2356+
23502357 for (uint32_t i = 0 ; i < setCount; i++) {
23512358 const auto set_layout = pipeline_layout->set_layouts [firstSet + i];
23522359 if ((set_layout->GetCreateFlags () & VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT) == 0 ) {
@@ -2360,107 +2367,80 @@ bool CoreChecks::ValidateCmdSetDescriptorBufferOffsets(const vvl::CommandBuffer
23602367 continue ;
23612368 }
23622369
2363- bool valid_buffer = false ;
2364- const VkDeviceAddress offset = pOffsets[i];
23652370 const uint32_t buffer_index = pBufferIndices[i];
2366- if (buffer_index < cb_state.descriptor_buffer_binding_info .size ()) {
2367- bool valid_binding = false ;
2368- const VkDeviceAddress start = cb_state.descriptor_buffer_binding_info [buffer_index].address ;
2369- const auto buffer_states = GetBuffersByAddress (start);
2370-
2371- if (!buffer_states.empty ()) {
2372- const auto buffer_state_starts = GetBuffersByAddress (start + offset);
2373-
2374- if (!buffer_state_starts.empty ()) {
2375- const auto bindings = set_layout->GetBindings ();
2376-
2377- VkDeviceSize set_layout_size = 0 ;
2378- if (VkDeviceSize cached_set_layout_size = set_layout->GetLayoutSizeInBytes (); cached_set_layout_size == 0 ) {
2379- DispatchGetDescriptorSetLayoutSizeEXT (cb_state.dev_data .device , set_layout->VkHandle (), &set_layout_size);
2380- auto set_layout_ptr = const_cast <vvl::DescriptorSetLayout *>(set_layout.get ());
2381- set_layout_ptr->SetLayoutSizeInBytes (&set_layout_size);
2382- } else {
2383- set_layout_size = cached_set_layout_size;
2384- }
2371+ if (buffer_index >= cb_state.descriptor_buffer_binding_info .size ()) {
2372+ const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-pBufferIndices-08065"
2373+ : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-pBufferIndices-08065" ;
2374+ const LogObjectList objlist (cb_state.Handle (), set_layout->Handle (), pipeline_layout->Handle ());
2375+ skip |= LogError (vuid, objlist, loc.dot (Field::pBufferIndices, i),
2376+ " is %" PRIu32 " but the command buffer only has had %zu bound descriptor buffers" , pBufferIndices[i],
2377+ cb_state.descriptor_buffer_binding_info .size ());
2378+ continue ; // the buffer is not valid
2379+ }
23852380
2386- if (set_layout_size > 0 ) {
2387- // It looks like enough to check last binding in set
2388- for (uint32_t j = 0 ; j < set_layout->GetBindingCount (); j++) {
2389- const VkDescriptorBindingFlags flags = set_layout->GetDescriptorBindingFlagsFromIndex (j);
2390- const bool vdc = (flags & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT) != 0 ;
2391-
2392- if (vdc) {
2393- // If a binding is VARIABLE_DESCRIPTOR_COUNT, the effective setLayoutSize we
2394- // must validate is just the offset of the last binding.
2395- const auto pool = cb_state.command_pool ;
2396- uint32_t binding = set_layout->GetDescriptorSetLayoutBindingPtrFromIndex (j)->binding ;
2397- DispatchGetDescriptorSetLayoutBindingOffsetEXT (pool->dev_data .device , set_layout->VkHandle (),
2398- binding, &set_layout_size);
2399-
2400- // If the descriptor set only consists of VARIABLE_DESCRIPTOR_COUNT bindings, the
2401- // offset may be 0. In this case, treat the descriptor set layout as size 1,
2402- // so we validate that the offset is sensible.
2403- if (set_layout->GetBindingCount () == 1 ) {
2404- set_layout_size = 1 ;
2405- }
2381+ const VkDescriptorBufferBindingInfoEXT &binding_info = cb_state.descriptor_buffer_binding_info [buffer_index];
2382+ const VkDeviceAddress start = binding_info.address ;
2383+ const auto buffer_states = GetBuffersByAddress (start);
24062384
2407- // There can only be one binding with VARIABLE_COUNT.
2408- break ;
2409- }
2410- }
2411- }
2385+ if (buffer_states.empty ()) {
2386+ const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-pBufferIndices-08065"
2387+ : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-pBufferIndices-08065" ;
2388+ const LogObjectList objlist (cb_state.Handle (), set_layout->Handle (), pipeline_layout->Handle ());
2389+ skip |=
2390+ LogError (vuid, objlist, loc.dot (Field::pBufferIndices, i),
2391+ " (%" PRIu32 " ) points to descriptor buffer at VkDescriptorBufferBindingInfoEXT::address (0x%" PRIxLEAST64
2392+ " ) but no VkBuffer was found in this address" ,
2393+ buffer_index, start);
2394+ continue ; // the buffer is not valid
2395+ }
24122396
2413- if (set_layout_size > 0 ) {
2414- const auto buffer_state_ends = GetBuffersByAddress (start + offset + set_layout_size - 1 );
2415- if (!buffer_state_ends.empty ()) {
2416- valid_binding = true ;
2417- }
2397+ const VkDeviceAddress offset = pOffsets[i];
2398+ if (offset == 0 ) {
2399+ continue ; // is by definition small enough as it is at the start
2400+ }
2401+
2402+ bool valid_binding = false ;
2403+ VkDeviceSize set_layout_size = set_layout->GetLayoutSizeInBytes ();
2404+ const auto buffer_state_starts = GetBuffersByAddress (start + offset);
2405+ if (!buffer_state_starts.empty ()) {
2406+ const auto bindings = set_layout->GetBindings ();
2407+
2408+ if (set_layout_size > 0 ) {
2409+ // Variable Descriptor Count can only be in the highest binding (the last binding)
2410+ const uint32_t last_index = set_layout->GetLastIndex ();
2411+ const VkDescriptorBindingFlags flags = set_layout->GetDescriptorBindingFlagsFromIndex (last_index);
2412+ if (flags & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT) {
2413+ // If the descriptor set only consists of VARIABLE_DESCRIPTOR_COUNT bindings, the offset may be 0. In
2414+ // this case, treat the descriptor set layout as size 1, so we validate that the offset is sensible.
2415+ if (set_layout->GetBindingCount () == 1 ) {
2416+ set_layout_size = 1 ;
2417+ } else {
2418+ // If a binding is VARIABLE_DESCRIPTOR_COUNT, the effective setLayoutSize we must validate is just
2419+ // the offset of the last binding.
2420+ const uint32_t binding = set_layout->GetDescriptorSetLayoutBindingPtrFromIndex (last_index)->binding ;
2421+ DispatchGetDescriptorSetLayoutBindingOffsetEXT (device, set_layout->VkHandle (), binding, &set_layout_size);
24182422 }
24192423 }
2420-
2421- valid_buffer = true ;
24222424 }
24232425
2424- if (!valid_binding) {
2425- const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-pOffsets-08063"
2426- : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-pOffsets-08063" ;
2427- skip |= LogError (vuid, cb_state.Handle (), loc.dot (Field::pOffsets, i),
2428- " %" PRIuLEAST64
2429- " must be small enough such that any descriptor binding"
2430- " referenced by layout without the VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT"
2431- " flag computes a valid address inside the underlying VkBuffer" ,
2432- pOffsets[i]);
2426+ if (set_layout_size > 0 ) {
2427+ const auto buffer_state_ends = GetBuffersByAddress (start + offset + set_layout_size - 1 );
2428+ if (!buffer_state_ends.empty ()) {
2429+ valid_binding = true ;
2430+ }
24332431 }
24342432 }
24352433
2436- if (!valid_buffer) {
2437- const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-pBufferIndices-08065"
2438- : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-pBufferIndices-08065" ;
2439- skip |= LogError (vuid, cb_state.Handle (), loc.dot (Field::pBufferIndices, i),
2440- " (%" PRIu32
2441- " ) Each element of pBufferIndices must reference a valid descriptor buffer binding "
2442- " set by a previous call to vkCmdBindDescriptorBuffersEXT in commandBuffer" ,
2443- pBufferIndices[i]);
2444- }
2445-
2446- if (pBufferIndices[i] >= phys_dev_ext_props.descriptor_buffer_props .maxDescriptorBufferBindings ) {
2447- const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-pBufferIndices-08064"
2448- : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-pBufferIndices-08064" ;
2449- skip |= LogError (vuid, cb_state.Handle (), loc.dot (Field::pBufferIndices, i),
2450- " (%" PRIu32
2451- " ) "
2452- " is greater than maxDescriptorBufferBindings (%" PRIu32 " ) " ,
2453- pBufferIndices[i], phys_dev_ext_props.descriptor_buffer_props .maxDescriptorBufferBindings );
2454- }
2455-
2456- if (SafeModulo (offset, phys_dev_ext_props.descriptor_buffer_props .descriptorBufferOffsetAlignment ) != 0 ) {
2457- const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-pOffsets-08061"
2458- : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-pOffsets-08061" ;
2459- skip |= LogError (vuid, cb_state.Handle (), loc.dot (Field::pOffsets, i),
2460- " (%" PRIuLEAST64
2461- " ) is not aligned to descriptorBufferOffsetAlignment"
2462- " (%" PRIuLEAST64 " )" ,
2463- offset, phys_dev_ext_props.descriptor_buffer_props .descriptorBufferOffsetAlignment );
2434+ if (!valid_binding) {
2435+ const char *vuid = is_2 ? " VUID-VkSetDescriptorBufferOffsetsInfoEXT-pOffsets-08063"
2436+ : " VUID-vkCmdSetDescriptorBufferOffsetsEXT-pOffsets-08063" ;
2437+ const LogObjectList objlist (cb_state.Handle (), set_layout->Handle (), pipeline_layout->Handle ());
2438+ skip |=
2439+ LogError (vuid, objlist, loc.dot (Field::pBufferIndices, i),
2440+ " (%" PRIu32 " ) points to descriptor buffer at VkDescriptorBufferBindingInfoEXT::address (0x%" PRIxLEAST64
2441+ " ) and the pOffsets[%" PRIu32 " ] (%" PRIu64 " ) with a VkDescriptorSetLayout size %" PRIu64
2442+ " is not within any VkBuffer range" ,
2443+ buffer_index, start, i, offset, set_layout_size);
24642444 }
24652445 }
24662446
0 commit comments