/* Copyright (c) 2015-2024 The Khronos Group Inc. * Copyright (c) 2015-2024 Valve Corporation * Copyright (c) 2015-2024 LunarG, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "state_tracker/buffer_state.h" #include "containers/custom_containers.h" #include "error_message/logging.h" #include <array> #include <functional> #include <string> #include <string_view> /* This class aims at helping with the validation of a family of VUIDs referring to the same buffer device address. For example, take those VUIDs for VkDescriptorBufferBindingInfoEXT: VUID-VkDescriptorBufferBindingInfoEXT-usage-08122: If usage includes VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT, address must be an address within a valid buffer that was created with VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT VUID-VkDescriptorBufferBindingInfoEXT-usage-08123: If usage includes VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, address must be an address within a valid buffer that was created with VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT VUID-VkDescriptorBufferBindingInfoEXT-usage-08124: If usage includes VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT, address must be an address within a valid buffer that was created with VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT For usage to be valid, since the mentioned address can refer to multiple buffers, one must find a buffer that satisfies *all* of them. One must *not* consider those VUIDs independantly, each time trying to find a buffer that satisfies the considered VUID but not necessarily the others in the family. The VVL heuristic wants that the vast majority of the time, functions calls and structures are valid, thus validation should be fast and avoid to do things related to error logging unless necessary. To comply with that, buffer address validation is done in two passes: one to look for a buffer satisfying all VUIDs of the considered family. If none is found, another pass is done, this time building a per VUID error message (not per buffer) regrouping all buffers violating it. Outputting for each buffer every VUID it violates would lead to unnecessary log clutter. This two pass process is tedious to do without an helper class, hence BufferAddressValidation was created. The idea is to ask for user to provide the only necessary data: a VUID, how it is validated, what to log when a buffer violates it, and a snippet of text appended to the error message header. Then, just a call to LogErrorsIfNoValidBuffer is needed to do validation and, eventually, error logging. For an example of how to use BufferAddressValidation, see for instance how "VUID-VkDescriptorBufferBindingInfoEXT-usage-08122" and friends are validated. */ template <size_t ChecksCount = 1> class BufferAddressValidation { … }; template <size_t ChecksCount> bool BufferAddressValidation<ChecksCount>::HasValidBuffer(vvl::span<vvl::Buffer* const> buffer_list) const noexcept { … } template <size_t ChecksCount> bool BufferAddressValidation<ChecksCount>::HasInvalidBuffer(vvl::span<vvl::Buffer* const> buffer_list) const noexcept { … } template <size_t ChecksCount> bool BufferAddressValidation<ChecksCount>::LogInvalidBuffers(const CoreChecks& checker, vvl::span<vvl::Buffer* const> buffer_list, const Location& device_address_loc, const LogObjectList& objlist, VkDeviceAddress device_address) const noexcept { … }