| /* Copyright (c) 2015-2024 The Khronos Group Inc. |
| * Copyright (c) 2015-2024 Valve Corporation |
| * Copyright (c) 2015-2024 LunarG, Inc. |
| * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. |
| * Modifications Copyright (C) 2022 RasterGrid Kft. |
| * |
| * 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. |
| */ |
| |
| #include "best_practices/best_practices_validation.h" |
| #include "best_practices/bp_state.h" |
| |
| struct VendorSpecificInfo { |
| EnableFlags vendor_id; |
| std::string name; |
| }; |
| |
| const auto& GetVendorInfo() { |
| static const std::map<BPVendorFlagBits, VendorSpecificInfo> kVendorInfo = { |
| {kBPVendorArm, {vendor_specific_arm, "Arm"}}, |
| {kBPVendorAMD, {vendor_specific_amd, "AMD"}}, |
| {kBPVendorIMG, {vendor_specific_img, "IMG"}}, |
| {kBPVendorNVIDIA, {vendor_specific_nvidia, "NVIDIA"}}}; |
| |
| return kVendorInfo; |
| } |
| |
| ReadLockGuard BestPractices::ReadLock() const { |
| if (global_settings.fine_grained_locking) { |
| return ReadLockGuard(validation_object_mutex, std::defer_lock); |
| } else { |
| return ReadLockGuard(validation_object_mutex); |
| } |
| } |
| |
| WriteLockGuard BestPractices::WriteLock() { |
| if (global_settings.fine_grained_locking) { |
| return WriteLockGuard(validation_object_mutex, std::defer_lock); |
| } else { |
| return WriteLockGuard(validation_object_mutex); |
| } |
| } |
| |
| std::shared_ptr<vvl::CommandBuffer> BestPractices::CreateCmdBufferState(VkCommandBuffer handle, |
| const VkCommandBufferAllocateInfo* allocate_info, |
| const vvl::CommandPool* pool) { |
| return std::static_pointer_cast<vvl::CommandBuffer>( |
| std::make_shared<bp_state::CommandBuffer>(*this, handle, allocate_info, pool)); |
| } |
| |
| bp_state::CommandBuffer::CommandBuffer(BestPractices& bp, VkCommandBuffer handle, const VkCommandBufferAllocateInfo* allocate_info, |
| const vvl::CommandPool* pool) |
| : vvl::CommandBuffer(bp, handle, allocate_info, pool) {} |
| |
| bool BestPractices::VendorCheckEnabled(BPVendorFlags vendors) const { |
| for (const auto& vendor : GetVendorInfo()) { |
| if (vendors & vendor.first && enabled[vendor.second.vendor_id]) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| const char* BestPractices::VendorSpecificTag(BPVendorFlags vendors) const { |
| // Cache built vendor tags in a map |
| static vvl::unordered_map<BPVendorFlags, std::string> tag_map; |
| |
| auto res = tag_map.find(vendors); |
| if (res == tag_map.end()) { |
| // Build the vendor tag string |
| std::stringstream vendor_tag; |
| |
| vendor_tag << "["; |
| bool first_vendor = true; |
| for (const auto& vendor : GetVendorInfo()) { |
| if (vendors & vendor.first) { |
| if (!first_vendor) { |
| vendor_tag << ", "; |
| } |
| vendor_tag << vendor.second.name; |
| first_vendor = false; |
| } |
| } |
| vendor_tag << "]"; |
| |
| tag_map[vendors] = vendor_tag.str(); |
| res = tag_map.find(vendors); |
| } |
| |
| return res->second.c_str(); |
| } |
| |
| // Despite the return code being successful this can be a useful utility for some developers in niche debugging situation. |
| void BestPractices::LogPositiveSuccessCode(const RecordObject& record_obj) const { |
| assert(record_obj.result > VK_SUCCESS); |
| |
| LogVerbose("BestPractices-Verbose-Success-Logging", instance, record_obj.location, "Returned %s.", |
| string_VkResult(record_obj.result)); |
| } |
| |
| void BestPractices::LogErrorCode(const RecordObject& record_obj) const { |
| assert(record_obj.result < VK_SUCCESS); // Anything less than VK_SUCCESS is an error. |
| |
| // Despite being error codes log these results as informational. |
| // That is because they are returned frequently during window resizing. |
| // They are expected to occur during the normal application lifecycle. |
| constexpr std::array common_failure_codes = {VK_ERROR_OUT_OF_DATE_KHR, VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT}; |
| const auto result_string = string_VkResult(record_obj.result); |
| |
| if (IsValueIn(record_obj.result, common_failure_codes)) { |
| LogInfo("BestPractices-Failure-Result", instance, record_obj.location, "Returned error %s.", result_string); |
| } else { |
| LogWarning("BestPractices-Error-Result", instance, record_obj.location, "Returned error %s.", result_string); |
| } |
| } |