diff --git a/CMakeLists.txt b/CMakeLists.txt index b297c4d..ae93cb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,19 @@ +####################################################################################################################### +### Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. +### \author AMD Developer Tools Team +####################################################################################################################### + cmake_minimum_required(VERSION 3.11) set(SYSTEM_INFO_BUILD_RDF_INTERFACES ON) + ## Specify the top level name of the project - this will define the solution name for Visual Studio project(RMV) # Define version information set(RMV_MAJOR_VERSION 1) -set(RMV_MINOR_VERSION 8) +set(RMV_MINOR_VERSION 9) if (NOT RMV_BUGFIX_NUMBER) set(RMV_BUGFIX_NUMBER 0) endif () @@ -54,6 +60,7 @@ ELSE(WIN32) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/../../debug) ENDIF(WIN32) + # Add for CentOS compiler warning add_definitions(-DJSON_SKIP_UNSUPPORTED_COMPILER_CHECK) @@ -116,13 +123,6 @@ set_target_properties(QtCustomWidgets PROPERTIES FOLDER Dependencies ) -ELSEIF(APPLE) -set_property(GLOBAL PROPERTY USE_FOLDERS ON) -set_target_properties(QtCustomWidgets - QtUtils - PROPERTIES - FOLDER Dependencies -) ENDIF() IF(WIN32) @@ -136,11 +136,7 @@ ENDIF(WIN32) # This is evaluated at project build time - not at CMake generation time set(BUILD_ROOT $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}>$<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}>) -if(APPLE) - set(DOCS_OUTPUT_DIR $/../Resources) -else() - set(DOCS_OUTPUT_DIR ${BUILD_ROOT}) -endif() +set(DOCS_OUTPUT_DIR ${BUILD_ROOT}) # group sphinx source files into a sphinx folder file(GLOB SPHINX_DOC_FILES ${SPHINX_DOC_FILES} ${CMAKE_SOURCE_DIR}/documentation/source/*.rst) @@ -168,9 +164,6 @@ if(SPHINX_EXECUTABLE) # Sphinx has proper dependency checking, so this works as expected. # Once built, clean up any unneeded files. add_custom_target(Documentation ALL SOURCES ${ALL_SPHINX_FILES} ${RELEASE_DOCS} DEPENDS sphinx_output) - if(APPLE) - add_dependencies(Documentation RadeonMemoryVisualizer) - endif() add_custom_command(MAIN_DEPENDENCY ${SPHINX_DOC_MAIN} OUTPUT sphinx_output COMMAND ${CMAKE_COMMAND} -E echo "building Sphinx documentation" COMMAND ${SPHINX_EXECUTABLE} ${CMAKE_SOURCE_DIR}/documentation/source ${DOCS_OUTPUT_DIR}/help/rmv/. -t ${SPHINX_OPTION} @@ -201,3 +194,5 @@ add_custom_command(TARGET Documentation POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${DOCS_OUTPUT_DIR}/samples COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/samples/sample_trace.rmv ${DOCS_OUTPUT_DIR}/samples/. ) + + diff --git a/build/dependency_map.py b/build/dependency_map.py index 92b7de0..8329b0d 100644 --- a/build/dependency_map.py +++ b/build/dependency_map.py @@ -1,6 +1,6 @@ #! python3 ##============================================================================= -## Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +## Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. ## \author AMD Developer Tools Team ## \file ## \brief List of all external dependencies. diff --git a/build/fetch_dependencies.py b/build/fetch_dependencies.py index e64dc13..3c3e2dc 100644 --- a/build/fetch_dependencies.py +++ b/build/fetch_dependencies.py @@ -1,6 +1,6 @@ #! python3 ##============================================================================= -## Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +## Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. ## \author AMD Developer Tools Team ## \file ## \brief Script to fetch all external git and/or downloadable dependencies diff --git a/build/pre_build.py b/build/pre_build.py index 34c77dc..be1b8ee 100644 --- a/build/pre_build.py +++ b/build/pre_build.py @@ -1,6 +1,6 @@ #! python3 ##============================================================================= -## Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +## Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. ## \author AMD Developer Tools Team ## \file ## \brief Script to perform all necessary pre build steps. This includes: @@ -66,7 +66,6 @@ parser.add_argument("--qt", default="5.15.2", help="specify the version of QT to be used with the script (default: 5.15.2)" ) parser.add_argument("--clean", action="store_true", help="delete any directories created by this script") parser.add_argument("--no-qt", action="store_true", help="build a headless version (not applicable for all products)") -parser.add_argument("--build-number", default="0", help="specify the build number, primarily to be used by build machines to produce versioned builds") parser.add_argument("--update", action="store_true", help="Force fetch_dependencies script to update all dependencies") parser.add_argument("--output", default=output_root, help="specify the output location for generated cmake and build output files (default = OS specific subdirectory of location of PreBuild.py script)") parser.add_argument("--build", action="store_true", help="build all supported configurations on completion of prebuild step") @@ -263,8 +262,6 @@ def generate_config(config): if args.qt_system: cmake_args.extend(["-DQT_SYSTEM:BOOL=TRUE"]) - cmake_args.extend(["-DRMV_BUILD_NUMBER=" + str(args.build_number)]) - cmake_args.extend(["-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=" + release_output_dir]) cmake_args.extend(["-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE=" + release_output_dir]) cmake_args.extend(["-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG=" + debug_output_dir]) @@ -387,3 +384,4 @@ def generate_config(config): minutes, seconds = divmod(time.time() - start_time, 60) log_print("Successfully completed in {0:.0f} minutes, {1:.1f} seconds".format(minutes,seconds)) sys.exit(0) + diff --git a/cmake/dev_tools.cmake b/cmake/dev_tools.cmake index 8bc2f68..954f44d 100644 --- a/cmake/dev_tools.cmake +++ b/cmake/dev_tools.cmake @@ -1,5 +1,5 @@ ####################################################################################################################### -### Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +### Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. ### \author AMD Developer Tools Team ####################################################################################################################### @@ -71,3 +71,4 @@ function(devtools_target_options name) endif () endfunction() + diff --git a/cmake/devtools_qt_helper.cmake b/cmake/devtools_qt_helper.cmake index 5824bb1..ad445bc 100644 --- a/cmake/devtools_qt_helper.cmake +++ b/cmake/devtools_qt_helper.cmake @@ -1,10 +1,11 @@ ####################################################################################################################### -### Copyright (c) 2019-2021 Advanced Micro Devices, Inc. All rights reserved. +### Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. ### @author AMD Developer Tools Team ####################################################################################################################### cmake_minimum_required(VERSION 3.10) + # Attempt to automatically find Qt on the local machine if (UNIX AND NOT APPLE) find_package(Qt6 QUIET COMPONENTS Core Widgets Network Gui Svg Test GuiPrivate CorePrivate) @@ -143,3 +144,4 @@ if (Qt5_DIR OR Qt6_DIR) endif () endfunction() endif () + diff --git a/source/backend/CMakeLists.txt b/source/backend/CMakeLists.txt index bfe3e8f..28ac1c8 100644 --- a/source/backend/CMakeLists.txt +++ b/source/backend/CMakeLists.txt @@ -1,14 +1,20 @@ +####################################################################################################################### +### Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. +### \author AMD Developer Tools Team +####################################################################################################################### + cmake_minimum_required(VERSION 3.10) project(RmvBackend) set(CMAKE_INCLUDE_CURRENT_DIR ON) -include_directories(AFTER ../backend ../parser ../../external/rdf/rdf/inc) +include_directories(AFTER ../backend ../parser ../../external/rdf/rdf/inc ../third_party) add_definitions(-DSYSTEM_INFO_ENABLE_RDF) add_definitions(-DRDF_CXX_BINDINGS) # List of all source files. It may be possible to have the build process call cmake to update the makefiles # only when this file has changed (ie source files have been added or removed) + set( SOURCES "rmt_adapter_info.cpp" "rmt_adapter_info.h" @@ -73,10 +79,10 @@ set( SOURCES ) set( LINUX_SOURCES - "../third_party/pevents/pevents.cpp" - "../third_party/pevents/pevents.h" + "rmt_include_pevents.cpp" ) + # specify output library name IF(WIN32) add_library(${PROJECT_NAME} ${SOURCES}) @@ -96,3 +102,4 @@ endforeach() ENDIF(WIN32) devtools_target_options(${PROJECT_NAME}) + diff --git a/source/backend/rmt_adapter_info.cpp b/source/backend/rmt_adapter_info.cpp index 4e16b01..3a2327a 100644 --- a/source/backend/rmt_adapter_info.cpp +++ b/source/backend/rmt_adapter_info.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Helper function for legacy adapter information captured for the target process. diff --git a/source/backend/rmt_adapter_info.h b/source/backend/rmt_adapter_info.h index a39159b..071a6aa 100644 --- a/source/backend/rmt_adapter_info.h +++ b/source/backend/rmt_adapter_info.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Helper function for legacy adapter information captured for the target process. diff --git a/source/backend/rmt_atomic.cpp b/source/backend/rmt_atomic.cpp index 23a57ab..9e027da 100644 --- a/source/backend/rmt_atomic.cpp +++ b/source/backend/rmt_atomic.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of atomic helper functions. diff --git a/source/backend/rmt_atomic.h b/source/backend/rmt_atomic.h index 9fe2291..edb2df3 100644 --- a/source/backend/rmt_atomic.h +++ b/source/backend/rmt_atomic.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of platform-abstracted atomic functions. diff --git a/source/backend/rmt_configuration.h b/source/backend/rmt_configuration.h index 5297278..35fdbe9 100644 --- a/source/backend/rmt_configuration.h +++ b/source/backend/rmt_configuration.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Global configuration values for the RMT backend. diff --git a/source/backend/rmt_data_profile.h b/source/backend/rmt_data_profile.h index d7bcbc0..06fdc14 100644 --- a/source/backend/rmt_data_profile.h +++ b/source/backend/rmt_data_profile.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Structures for profiling the RMT data for future parsing. diff --git a/source/backend/rmt_data_set.cpp b/source/backend/rmt_data_set.cpp index a10b173..6d566f9 100644 --- a/source/backend/rmt_data_set.cpp +++ b/source/backend/rmt_data_set.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of functions for working with a data set. @@ -703,6 +703,9 @@ static RmtErrorCode AllocateMemoryForSnapshot(RmtDataSet* data_set, RmtDataSnaps return kRmtOk; } +void UpdateTotalResourceUsageAliasedSize(RmtResourceList* resource_list, + RmtMemoryAliasingTimelineAlgorithm::RmtMemoryAliasingCalculator* memory_aliasing_calculator); + // consume next RMT token for snapshot generation. static RmtErrorCode ProcessTokenForSnapshot(RmtDataSet* data_set, RmtToken* current_token, RmtDataSnapshot* out_snapshot) { @@ -724,14 +727,7 @@ static RmtErrorCode ProcessTokenForSnapshot(RmtDataSet* data_set, RmtToken* curr RmtMemoryAliasingCalculator* memory_aliasing_calculator = RmtMemoryAliasingCalculatorInstance(); RMT_ASSERT(memory_aliasing_calculator != nullptr); memory_aliasing_calculator->DestroyAllocation(virtual_allocation->allocation_identifier); - SizePerResourceUsageType sizes_per_resource_usage_type; - SizeType unbound_size; - memory_aliasing_calculator->CalculateSizes(sizes_per_resource_usage_type, unbound_size); - for (int usage_index = 0; usage_index < RmtResourceUsageType::kRmtResourceUsageTypeCount; usage_index++) - { - out_snapshot->resource_list.total_resource_usage_aliased_size[usage_index] = sizes_per_resource_usage_type.size_[usage_index]; - } - out_snapshot->resource_list.total_resource_usage_aliased_size[kRmtResourceUsageTypeFree] = unbound_size; + UpdateTotalResourceUsageAliasedSize(&out_snapshot->resource_list, memory_aliasing_calculator); } error_code = RmtVirtualAllocationListRemoveAllocation(&out_snapshot->virtual_allocation_list, current_token->virtual_free_token.virtual_address); RMT_ASSERT(error_code == kRmtOk); @@ -800,8 +796,19 @@ static RmtErrorCode ProcessTokenForSnapshot(RmtDataSet* data_set, RmtToken* curr { if (!data_set->flags.userdata_processed) { - RmtResourceUserdataTrackImplicitResourceToken( - current_token->userdata_token.resource_identifier, current_token->common.timestamp, current_token->userdata_token.time_delay); + // If the HeapType is missing from the MarkImplicitResource token (traces prior to RMT Spec version 1.9), assume the implicit resource is a buffer or image. + if (current_token->userdata_token.implicit_resource_type == RmtImplicitResourceType::kRmtImplicitResourceTypeUnused) + { + current_token->userdata_token.implicit_resource_type = RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitResource; + } + else + { + data_set->flags.implicit_heap_detection = true; + } + RmtResourceUserdataTrackImplicitResourceToken(current_token->userdata_token.resource_identifier, + current_token->common.timestamp, + current_token->userdata_token.time_delay, + current_token->userdata_token.implicit_resource_type); } } } @@ -829,7 +836,7 @@ static RmtErrorCode ProcessTokenForSnapshot(RmtDataSet* data_set, RmtToken* curr if (!RmtResourceUserDataIsResourceImplicit(current_token->resource_bind_token.resource_identifier)) { - error_code = RmtResourceListAddResourceBind(&out_snapshot->resource_list, ¤t_token->resource_bind_token); + error_code = RmtResourceListAddResourceBind(&out_snapshot->resource_list, ¤t_token->resource_bind_token, !data_set->flags.userdata_processed); if (error_code == kRmtErrorSharedAllocationNotFound) { @@ -903,7 +910,8 @@ static RmtErrorCode ProcessTokenForSnapshot(RmtDataSet* data_set, RmtToken* curr if (!(current_token->resource_bind_token.is_system_memory && current_token->resource_bind_token.virtual_address == 0)) { // Re-bind the resource to its new virtual memory allocation. - error_code = RmtResourceListAddResourceBind(&out_snapshot->resource_list, ¤t_token->resource_bind_token); + error_code = RmtResourceListAddResourceBind( + &out_snapshot->resource_list, ¤t_token->resource_bind_token, !data_set->flags.userdata_processed); RMT_ASSERT(error_code == kRmtOk); } } @@ -1139,10 +1147,12 @@ RmtErrorCode RmtDataSetInitialize(const char* path, RmtDataSet* data_set) memcpy(data_set->file_path, path, RMT_MINIMUM(RMT_MAXIMUM_FILE_PATH, path_length)); memcpy(data_set->temporary_file_path, path, RMT_MINIMUM(RMT_MAXIMUM_FILE_PATH, path_length)); - data_set->file_handle = NULL; - data_set->flags.read_only = false; - data_set->flags.is_rdf_trace = false; - data_set->active_gpu = 0; + data_set->file_handle = NULL; + data_set->flags.read_only = false; + data_set->flags.is_rdf_trace = false; + data_set->flags.implicit_heap_detection = false; + data_set->active_gpu = 0; + errno_t error_no; bool file_transfer_result = false; if (IsFileReadOnly(path) || IsCrashDumpFile(path)) @@ -1254,6 +1264,12 @@ RmtErrorCode RmtDataSetInitialize(const char* path, RmtDataSet* data_set) } } + // Vega and older GPUs are no longer supported. + if (error_code == kRmtOk && data_set->system_info.pcie_family_id < kGfx10AsicFamily) + { + error_code = kRmtErrorTraceFileNotSupported; + } + if (error_code == kRmtOk) { CheckForSAMSupport(data_set); @@ -1324,6 +1340,7 @@ RmtErrorCode RmtDataSetDestroy(RmtDataSet* data_set) } data_set->virtual_allocation_list.allocation_count = 0; + RmtResourceUserDataCleanup(); return kRmtOk; } @@ -1686,6 +1703,9 @@ static RmtErrorCode SnapshotGeneratorConvertHeapsToBuffers(RmtDataSnapshot* snap current_resource->buffer.usage_flags = 0; current_resource->buffer.size_in_bytes = heap_size_in_bytes; current_resource->resource_type = kRmtResourceTypeBuffer; + + // Increment the non-heap count since the heap has been converted to a buffer resource. + current_virtual_allocation->non_heap_resource_count++; } return kRmtOk; @@ -1785,7 +1805,7 @@ static RmtErrorCode MergeResourceMemoryRegions(const RmtVirtualAllocation* virtu RMT_RETURN_ON_ERROR(virtual_allocation != nullptr, kRmtErrorInvalidPointer); out_bound_regions.clear(); - if (virtual_allocation->resource_count == 0) + if (virtual_allocation->non_heap_resource_count == 0) { return kRmtOk; } @@ -1870,6 +1890,16 @@ static RmtErrorCode SnapshotGeneratorAddUnboundResources(RmtDataSnapshot* snapsh size_t last_bound_region_index = bound_regions.size() - 1; ///< The index of the last bound memory region. RmtMemoryRegion previous_bound_region({bound_regions[0].offset, bound_regions[0].size}); + + if (previous_bound_region.offset > 0) + { + // Create an unbound region before the first bound region. + RmtMemoryRegion unbound_region; + unbound_region.offset = 0; + unbound_region.size = previous_bound_region.offset; + unbound_regions.push_back(unbound_region); + } + for (size_t i = 1; i < bound_regions.size(); i++) { const RmtMemoryRegion current_bound_region = bound_regions[i]; @@ -2049,6 +2079,72 @@ static RmtErrorCode SnapshotGeneratorCalculateSnapshotPointSummary(RmtDataSnapsh return kRmtOk; } +/// @brief Update the names of virtual allocations if a named heap resource is bound to it. +/// +/// @param [in/out] out_snapshot A pointer to the snapshot to be updated. +/// +/// @retval +/// kRmtOk The operation completed successfully. +/// @retval +/// kRmtErrorInvalidPointer The operation failed because out_snapshot was NULL. +/// +static RmtErrorCode SnapshotGeneratorUpdateNamedHeaps(RmtDataSnapshot* out_snapshot) +{ + RMT_RETURN_ON_ERROR(out_snapshot, kRmtErrorInvalidPointer); + + const int32_t allocation_count = out_snapshot->virtual_allocation_list.allocation_count; + for (int32_t allocation_index = 0; allocation_index < allocation_count; allocation_index++) + { + // Get a reference to the allocation object so that its name can be updated. + RmtVirtualAllocation& allocation = out_snapshot->virtual_allocation_list.allocation_details[allocation_index]; + const int heap_resource_count = allocation.resource_count - allocation.non_heap_resource_count; + RMT_ASSERT(heap_resource_count <= 1); + + const RmtResource* first_heap_resource = nullptr; + const RmtResource* first_non_heap_resource = nullptr; + const char* first_heap_resource_name = nullptr; + const char* first_non_heap_resource_name = nullptr; + + for (int resource_index = 0; resource_index < allocation.resource_count; resource_index++) + { + const RmtResource* resource = allocation.resources[resource_index]; + if (resource->resource_type == RmtResourceType::kRmtResourceTypeHeap) + { + first_heap_resource = resource; + RmtResourceUserdataGetResourceName(first_heap_resource->identifier, &first_heap_resource_name); + if (first_non_heap_resource != nullptr) + { + break; + } + } + else + { + first_non_heap_resource = resource; + RmtResourceUserdataGetResourceName(first_non_heap_resource->identifier, &first_non_heap_resource_name); + if (first_heap_resource != nullptr) + { + break; + } + } + } + + if (heap_resource_count == 1 && first_heap_resource_name != nullptr) + { + allocation.name = first_heap_resource_name; + } + else if (allocation.non_heap_resource_count == 1 && first_non_heap_resource_name != NULL && first_non_heap_resource->address == allocation.base_address) + { + allocation.name = first_non_heap_resource_name; + } + else + { + allocation.name = nullptr; + } + } + + return kRmtOk; +} + // function to generate a snapshot. RmtErrorCode RmtDataSetGenerateSnapshot(RmtDataSet* data_set, RmtSnapshotPoint* snapshot_point, RmtDataSnapshot* out_snapshot) { @@ -2094,7 +2190,13 @@ RmtErrorCode RmtDataSetGenerateSnapshot(RmtDataSet* data_set, RmtSnapshotPoint* RMT_ASSERT(error_code == kRmtOk); } - SnapshotGeneratorConvertHeapsToBuffers(out_snapshot); + if (!data_set->flags.implicit_heap_detection) + { + // If the heap_type flag is missing from MarkImplicitResource tokens (as is the case with older traces), + // convert solitary heaps in an allocation into buffers. + SnapshotGeneratorConvertHeapsToBuffers(out_snapshot); + } + SnapshotGeneratorAddResourcePointers(out_snapshot); SnapshotGeneratorCompactVirtualAllocations(out_snapshot); SnapshotGeneratorAddUnboundResources(out_snapshot); @@ -2103,6 +2205,7 @@ RmtErrorCode RmtDataSetGenerateSnapshot(RmtDataSet* data_set, RmtSnapshotPoint* SnapshotGeneratorCalculateCommitType(out_snapshot); SnapshotGeneratorAllocateRegionStack(out_snapshot); SnapshotGeneratorCalculateSnapshotPointSummary(out_snapshot, snapshot_point); + SnapshotGeneratorUpdateNamedHeaps(out_snapshot); return kRmtOk; } diff --git a/source/backend/rmt_data_set.h b/source/backend/rmt_data_set.h index f28823d..7db4b02 100644 --- a/source/backend/rmt_data_set.h +++ b/source/backend/rmt_data_set.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Structures and functions for working with a data set. @@ -63,6 +63,7 @@ struct RmtDataSetFlags bool userdata_processed : 1; ///< Whether the userdata tokens have been processed yet. bool contains_correlation_tokens : 1; ///< Whether the dataset contains any correlation tokens. bool cancel_background_task_flag : 1; ///< If true, indicates a background task has been cancelled. + bool implicit_heap_detection : 1; ///< If true, indicates the trace includes data that can be used to determine if a heap is implicit. }; /// A structure encapsulating a single RMT dataset. @@ -288,4 +289,4 @@ void RmtDataSetCancelBackgroundTask(RmtDataSet* data_set); #ifdef __cplusplus } #endif // #ifdef __cplusplus -#endif // #ifndef RMV_BACKEND_RMT_DATA_SET_H_ +#endif // #ifndef RMV_BACKEND_RMT_DATA_SET_H_ \ No newline at end of file diff --git a/source/backend/rmt_data_snapshot.cpp b/source/backend/rmt_data_snapshot.cpp index 876fc3f..e33971f 100644 --- a/source/backend/rmt_data_snapshot.cpp +++ b/source/backend/rmt_data_snapshot.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Functions working on a snapshot. @@ -433,14 +433,15 @@ RmtErrorCode RmtDataSnapshotGetSegmentStatus(const RmtDataSnapshot* snapshot, Rm out_segment_status->total_physical_size = snapshot->data_set->segment_info[heap_type].size; out_segment_status->total_bound_virtual_memory = 0; + out_segment_status->allocation_count = 0; + out_segment_status->resource_count = 0; // calculate data for the segment info fields. uint64_t max_virtual_allocation_size = 0; uint64_t min_virtual_allocation_size = UINT64_MAX; uint64_t total_virtual_memory_requested = 0; uint64_t total_physical_mapped_by_process = snapshot->page_table.mapped_per_heap[heap_type]; - - uint64_t allocation_count = 0; + uint64_t allocation_count = 0; // set the resource committed memory values. for (int32_t current_resource_usage_index = 0; current_resource_usage_index < kRmtResourceUsageTypeCount; ++current_resource_usage_index) @@ -466,6 +467,8 @@ RmtErrorCode RmtDataSnapshotGetSegmentStatus(const RmtDataSnapshot* snapshot, Rm uint64_t memory_region_size = RmtVirtualAllocationGetTotalResourceMemoryInBytes(snapshot, current_virtual_allocation); out_segment_status->total_bound_virtual_memory += memory_region_size; RMT_ASSERT(size_in_bytes >= memory_region_size); + + out_segment_status->resource_count += current_virtual_allocation->non_heap_resource_count; } // Walk each resource in the allocation and work out what heap each resource is in. @@ -499,6 +502,8 @@ RmtErrorCode RmtDataSnapshotGetSegmentStatus(const RmtDataSnapshot* snapshot, Rm out_segment_status->total_physical_mapped_by_other_processes = 0; out_segment_status->max_allocation_size = max_virtual_allocation_size; out_segment_status->min_allocation_size = min_virtual_allocation_size; + out_segment_status->committed_size = snapshot->snapshot_point->committed_memory[heap_type]; + out_segment_status->allocation_count = allocation_count; if (allocation_count > 0) { out_segment_status->mean_allocation_size = total_virtual_memory_requested / allocation_count; diff --git a/source/backend/rmt_data_snapshot.h b/source/backend/rmt_data_snapshot.h index 726bd23..ce63579 100644 --- a/source/backend/rmt_data_snapshot.h +++ b/source/backend/rmt_data_snapshot.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Structures and functions for working with a snapshot. @@ -54,10 +54,13 @@ typedef struct RmtSegmentStatus uint64_t total_physical_mapped_by_process; ///< The total size (in bytes) of the physical memory mapped by the target process. uint64_t total_physical_mapped_by_other_processes; ///< The total size (in bytes) of the physical memory mapped by other processes. uint64_t peak_bandwidth_in_bytes_per_second; ///< The peak bandwidth (in bytes per second) that the RAM in the segment is capable of. + uint64_t allocation_count; ///< The number of allocations owned by this heap. uint64_t mean_allocation_size; ///< The mean allcation size (in bytes) of all allocations in this segment. uint64_t max_allocation_size; ///< The max allocation size (in bytes) of all allocations in this segment. uint64_t min_allocation_size; ///< The min allocation size (in bytes) of all allocations in this segment. - + uint64_t resource_count; ///< The number of resources owned by this heap. + uint64_t committed_size; ///< The amount of committed memory in bytes. + uint64_t physical_bytes_per_resource_usage[kRmtResourceUsageTypeCount]; ///< The amount of physical memory (in bytes) of each resource usage type. } RmtSegmentStatus; diff --git a/source/backend/rmt_data_timeline.cpp b/source/backend/rmt_data_timeline.cpp index f1b04b8..7e7dc05 100644 --- a/source/backend/rmt_data_timeline.cpp +++ b/source/backend/rmt_data_timeline.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the data timeline functions. diff --git a/source/backend/rmt_data_timeline.h b/source/backend/rmt_data_timeline.h index 77d6ff6..58fb37d 100644 --- a/source/backend/rmt_data_timeline.h +++ b/source/backend/rmt_data_timeline.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Data structures and functions to operate on a timeline. diff --git a/source/backend/rmt_include_pevents.cpp b/source/backend/rmt_include_pevents.cpp new file mode 100644 index 0000000..f30d22c --- /dev/null +++ b/source/backend/rmt_include_pevents.cpp @@ -0,0 +1,15 @@ +//============================================================================= +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. +/// @author AMD Developer Tools Team +/// @file +/// @brief Include the pevents source file the required pragmas. +/// +/// Switch off anything that will fail due to warnings as errors. +//============================================================================= + +#ifndef _WIN32 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#include "pevents/src/pevents.cpp" +#pragma GCC diagnostic pop +#endif diff --git a/source/backend/rmt_job_system.cpp b/source/backend/rmt_job_system.cpp index 0c8cd46..8bf2ccb 100644 --- a/source/backend/rmt_job_system.cpp +++ b/source/backend/rmt_job_system.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a job system to run work on multiple threads. diff --git a/source/backend/rmt_job_system.h b/source/backend/rmt_job_system.h index 12b284c..c9c8d9e 100644 --- a/source/backend/rmt_job_system.h +++ b/source/backend/rmt_job_system.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief A job system to run work on multiple threads. diff --git a/source/backend/rmt_legacy_snapshot_writer.cpp b/source/backend/rmt_legacy_snapshot_writer.cpp index 9f9b30d..431ae5b 100644 --- a/source/backend/rmt_legacy_snapshot_writer.cpp +++ b/source/backend/rmt_legacy_snapshot_writer.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the class that writes legacy trace snapshot data. diff --git a/source/backend/rmt_legacy_snapshot_writer.h b/source/backend/rmt_legacy_snapshot_writer.h index 384c0b7..0f4ffcc 100644 --- a/source/backend/rmt_legacy_snapshot_writer.h +++ b/source/backend/rmt_legacy_snapshot_writer.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Class that handles writing snapshot data to legacy trace files. diff --git a/source/backend/rmt_linear_buffer.cpp b/source/backend/rmt_linear_buffer.cpp index 63810db..5002cc7 100644 --- a/source/backend/rmt_linear_buffer.cpp +++ b/source/backend/rmt_linear_buffer.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the linear allocator helper functions. diff --git a/source/backend/rmt_linear_buffer.h b/source/backend/rmt_linear_buffer.h index 04b02a1..e326a6e 100644 --- a/source/backend/rmt_linear_buffer.h +++ b/source/backend/rmt_linear_buffer.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief A linear allocator structure and helper functions. diff --git a/source/backend/rmt_memory_aliasing_timeline.cpp b/source/backend/rmt_memory_aliasing_timeline.cpp index ad07fb7..51347c1 100644 --- a/source/backend/rmt_memory_aliasing_timeline.cpp +++ b/source/backend/rmt_memory_aliasing_timeline.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the aliasing resource memory algorithm. diff --git a/source/backend/rmt_memory_aliasing_timeline.h b/source/backend/rmt_memory_aliasing_timeline.h index 0481989..53e967f 100644 --- a/source/backend/rmt_memory_aliasing_timeline.h +++ b/source/backend/rmt_memory_aliasing_timeline.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definitions for the aliasing memory aliasing algorithm. @@ -48,22 +48,11 @@ namespace RmtMemoryAliasingTimelineAlgorithm return static_cast(pos); } -#elif defined __GNUC__ || defined __clang__ +#else if (mask) { return 31 - static_cast(__builtin_clz(mask)); } -#else - uint8_t pos = 31; - uint32_t bit = 1UL << 31; - do - { - if (mask & bit) - { - return pos; - } - bit >>= 1; - } while (pos-- > 0); #endif return UINT8_MAX; } diff --git a/source/backend/rmt_memory_event_history.cpp b/source/backend/rmt_memory_event_history.cpp index bbf5a4c..9309ba4 100644 --- a/source/backend/rmt_memory_event_history.cpp +++ b/source/backend/rmt_memory_event_history.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Memory Event History API. diff --git a/source/backend/rmt_memory_event_history.h b/source/backend/rmt_memory_event_history.h index f6210bd..36363be 100644 --- a/source/backend/rmt_memory_event_history.h +++ b/source/backend/rmt_memory_event_history.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Memory Event History API. diff --git a/source/backend/rmt_memory_event_history_impl.cpp b/source/backend/rmt_memory_event_history_impl.cpp index 4f13782..8bc2c5e 100644 --- a/source/backend/rmt_memory_event_history_impl.cpp +++ b/source/backend/rmt_memory_event_history_impl.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Private implementation of the memory history. diff --git a/source/backend/rmt_memory_event_history_impl.h b/source/backend/rmt_memory_event_history_impl.h index 196eb54..f6e2d37 100644 --- a/source/backend/rmt_memory_event_history_impl.h +++ b/source/backend/rmt_memory_event_history_impl.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Private Structures and functions for collecting memory event history. diff --git a/source/backend/rmt_mutex.cpp b/source/backend/rmt_mutex.cpp index 0977987..9c29792 100644 --- a/source/backend/rmt_mutex.cpp +++ b/source/backend/rmt_mutex.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementations of the mutex abstraction. diff --git a/source/backend/rmt_mutex.h b/source/backend/rmt_mutex.h index a402216..f8730c1 100644 --- a/source/backend/rmt_mutex.h +++ b/source/backend/rmt_mutex.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of a mutex abstraction. diff --git a/source/backend/rmt_page_table.cpp b/source/backend/rmt_page_table.cpp index ff94fcf..0857906 100644 --- a/source/backend/rmt_page_table.cpp +++ b/source/backend/rmt_page_table.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the page table helper functions. diff --git a/source/backend/rmt_page_table.h b/source/backend/rmt_page_table.h index d08317f..9485795 100644 --- a/source/backend/rmt_page_table.h +++ b/source/backend/rmt_page_table.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of structures and functions for a multi-level page table. diff --git a/source/backend/rmt_physical_allocation_list.cpp b/source/backend/rmt_physical_allocation_list.cpp index 86af561..dbbf99b 100644 --- a/source/backend/rmt_physical_allocation_list.cpp +++ b/source/backend/rmt_physical_allocation_list.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the physical allocation list functions. diff --git a/source/backend/rmt_physical_allocation_list.h b/source/backend/rmt_physical_allocation_list.h index c91ff5e..5044b63 100644 --- a/source/backend/rmt_physical_allocation_list.h +++ b/source/backend/rmt_physical_allocation_list.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Structures and functions for managing a physical allocation list. diff --git a/source/backend/rmt_pool.cpp b/source/backend/rmt_pool.cpp index 8057795..67bddc2 100644 --- a/source/backend/rmt_pool.cpp +++ b/source/backend/rmt_pool.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of functions for a fixed-size pool memory allocator. diff --git a/source/backend/rmt_pool.h b/source/backend/rmt_pool.h index 8814f2b..d5d4757 100644 --- a/source/backend/rmt_pool.h +++ b/source/backend/rmt_pool.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of structures and functions for a fixed-size pool diff --git a/source/backend/rmt_process_map.cpp b/source/backend/rmt_process_map.cpp index 67b36db..ea678db 100644 --- a/source/backend/rmt_process_map.cpp +++ b/source/backend/rmt_process_map.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the process map helper functions. diff --git a/source/backend/rmt_process_map.h b/source/backend/rmt_process_map.h index 84712d7..883b3e1 100644 --- a/source/backend/rmt_process_map.h +++ b/source/backend/rmt_process_map.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Data structures and functions to help construct a map of proc IDs. diff --git a/source/backend/rmt_process_start_info.h b/source/backend/rmt_process_start_info.h index ee84e64..a528ce8 100644 --- a/source/backend/rmt_process_start_info.h +++ b/source/backend/rmt_process_start_info.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of the process start info structures and helper functions. diff --git a/source/backend/rmt_rdf_file_parser.cpp b/source/backend/rmt_rdf_file_parser.cpp index c52495a..b256451 100644 --- a/source/backend/rmt_rdf_file_parser.cpp +++ b/source/backend/rmt_rdf_file_parser.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of functions for working with the RDF file format. @@ -130,8 +130,7 @@ static RmtErrorCode LoadSegmentChunk(rdfChunkFile* chunk_file, RmtDataSet* data_ { data_set->segment_info[count].base_address = data.physical_base_address; data_set->segment_info[count].heap_type = static_cast(data.type); - data_set->segment_info[count].index = - 0; /// TODO: This is missing from RDF spec (should be memory index, exposed by the Vulkan software stack) + data_set->segment_info[count].index = 0; data_set->segment_info[count].size = data.size; count++; } @@ -164,7 +163,7 @@ RmtRdfDataStream* GetRdfDataStreamFromParser(const RmtParser* rmt_parser) // Delete all instantiated RDF data streams for a trace. RmtErrorCode RmtRdfFileParserDestroyAllDataStreams() { - for (auto data_stream : data_stream_map) + for (auto& data_stream : data_stream_map) { delete data_stream.second; } @@ -295,7 +294,7 @@ static RmtErrorCode QueueDataStreamChunks(rdfChunkFile* chunk_file, RmtDataSet* } // Initialize a parser for each stream and pre-load the first chunk. - for (auto data_stream_item : data_stream_map) + for (auto& data_stream_item : data_stream_map) { const int32_t stream_index = data_stream_item.first; RmtRdfDataStream* data_stream = data_stream_item.second; diff --git a/source/backend/rmt_rdf_file_parser.h b/source/backend/rmt_rdf_file_parser.h index c4971a3..8db33d5 100644 --- a/source/backend/rmt_rdf_file_parser.h +++ b/source/backend/rmt_rdf_file_parser.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of the RFD File parser. diff --git a/source/backend/rmt_rdf_snapshot_writer.cpp b/source/backend/rmt_rdf_snapshot_writer.cpp index c275c8f..980b185 100644 --- a/source/backend/rmt_rdf_snapshot_writer.cpp +++ b/source/backend/rmt_rdf_snapshot_writer.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the class that handles writing snapshot data to RDF trace files. diff --git a/source/backend/rmt_rdf_snapshot_writer.h b/source/backend/rmt_rdf_snapshot_writer.h index 8778c43..ed56f33 100644 --- a/source/backend/rmt_rdf_snapshot_writer.h +++ b/source/backend/rmt_rdf_snapshot_writer.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Class that handles writing snapshot data to RDF trace files. diff --git a/source/backend/rmt_rdf_system_info.h b/source/backend/rmt_rdf_system_info.h index 739f9c0..5d49ad6 100644 --- a/source/backend/rmt_rdf_system_info.h +++ b/source/backend/rmt_rdf_system_info.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief The system information captured in the memory trace. diff --git a/source/backend/rmt_resource_history.cpp b/source/backend/rmt_resource_history.cpp index a03a069..55e24c8 100644 --- a/source/backend/rmt_resource_history.cpp +++ b/source/backend/rmt_resource_history.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of functions operating on a resource history structure. diff --git a/source/backend/rmt_resource_history.h b/source/backend/rmt_resource_history.h index 4ef13fb..1439b30 100644 --- a/source/backend/rmt_resource_history.h +++ b/source/backend/rmt_resource_history.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Structures and functions for working with a resource history. diff --git a/source/backend/rmt_resource_list.cpp b/source/backend/rmt_resource_list.cpp index 9084eb7..38f3008 100644 --- a/source/backend/rmt_resource_list.cpp +++ b/source/backend/rmt_resource_list.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the resource list functions. @@ -14,6 +14,7 @@ #include "rmt_data_snapshot.h" #include "rmt_address_helper.h" #include "rmt_print.h" +#include "rmt_resource_userdata.h" #include // for memcpy() @@ -501,6 +502,19 @@ static RmtErrorCode RemoveResourceFromTree(RmtResourceList* resource_list, RmtRe return kRmtOk; } +void UpdateTotalResourceUsageAliasedSize(RmtResourceList* resource_list, + RmtMemoryAliasingTimelineAlgorithm::RmtMemoryAliasingCalculator* memory_aliasing_calculator) +{ + SizePerResourceUsageType sizes_per_resource_usage_type; + SizeType unbound_size; + memory_aliasing_calculator->CalculateSizes(sizes_per_resource_usage_type, unbound_size); + for (int usage_index = 0; usage_index < RmtResourceUsageType::kRmtResourceUsageTypeCount; usage_index++) + { + resource_list->total_resource_usage_aliased_size[usage_index] = sizes_per_resource_usage_type.size_[usage_index]; + } + resource_list->total_resource_usage_aliased_size[kRmtResourceUsageTypeFree] = unbound_size; +} + // destroy a resource static RmtErrorCode DestroyResource(RmtResourceList* resource_list, RmtResource* resource) { @@ -516,7 +530,6 @@ static RmtErrorCode DestroyResource(RmtResourceList* resource_list, RmtResource* bool is_shareable = (resource->resource_type == kRmtResourceTypeImage) && ((resource->image.create_flags & kRmtImageCreationFlagShareable) == kRmtImageCreationFlagShareable); - RmtResourceUsageType resource_type = RmtResourceGetUsageType(resource); if ((!is_shareable && (resource_list->enable_aliased_resource_usage_sizes) && resource->bound_allocation != nullptr) && (RmtResourceGetUsageType(resource) != RmtResourceUsageType::kRmtResourceUsageTypeHeap)) { @@ -527,21 +540,10 @@ static RmtErrorCode DestroyResource(RmtResourceList* resource_list, RmtResource* { aliased_resource_allocation->DestroyResource( resource->address - resource->bound_allocation->base_address, resource->size_in_bytes, RmtResourceGetUsageType(resource)); - - SizePerResourceUsageType sizes_per_resource_usage_type; - SizeType unbound_size; - memory_aliasing_calculator->CalculateSizes(sizes_per_resource_usage_type, unbound_size); - for (int usage_index = 0; usage_index < RmtResourceUsageType::kRmtResourceUsageTypeCount; usage_index++) - { - resource_list->total_resource_usage_aliased_size[usage_index] = sizes_per_resource_usage_type.size_[usage_index]; - } - resource_list->total_resource_usage_aliased_size[kRmtResourceUsageTypeFree] = unbound_size; + UpdateTotalResourceUsageAliasedSize(resource_list, memory_aliasing_calculator); } } - RMT_ASSERT(resource_list->resource_usage_size[resource_type] >= resource->size_in_bytes); - resource_list->resource_usage_size[RmtResourceGetUsageType(resource)] -= resource->size_in_bytes; - const int64_t hashed_identifier = GenerateResourceHandle(resource->identifier); // get a pointer to the last resource, if its the one we're trying to delete then adjust the count. @@ -597,7 +599,6 @@ RmtErrorCode RmtResourceListInitialize(RmtResourceList* resource_ resource_list->root = NULL; memset(resource_list->resource_usage_count, 0, sizeof(resource_list->resource_usage_count)); - memset(resource_list->resource_usage_size, 0, sizeof(resource_list->resource_usage_size)); memset(resource_list->total_resource_usage_aliased_size, 0, sizeof(resource_list->total_resource_usage_aliased_size)); return kRmtOk; @@ -768,7 +769,7 @@ static void UpdateCommitType(RmtResourceList* resource_list, RmtResource* resour // snapshotGeneratorCalculateCommitType in rmt_data_set.cpp. } -RmtErrorCode RmtResourceListAddResourceBind(RmtResourceList* resource_list, const RmtTokenResourceBind* resource_bind) +RmtErrorCode RmtResourceListAddResourceBind(RmtResourceList* resource_list, const RmtTokenResourceBind* resource_bind, const bool track_user_data) { RMT_ASSERT(resource_list); RMT_RETURN_ON_ERROR(resource_list, kRmtErrorInvalidPointer); @@ -854,21 +855,16 @@ RmtErrorCode RmtResourceListAddResourceBind(RmtResourceList* resource_list, cons { aliased_resource_allocation->CreateResource( resource->address - resource->bound_allocation->base_address, resource->size_in_bytes, RmtResourceGetUsageType(resource)); - - SizePerResourceUsageType sizes_per_resource_type; - SizeType unbound_size; - memory_aliasing_calculator->CalculateSizes(sizes_per_resource_type, unbound_size); - for (int usage_index = 0; usage_index < RmtResourceUsageType::kRmtResourceUsageTypeCount; usage_index++) - { - resource_list->total_resource_usage_aliased_size[usage_index] = sizes_per_resource_type.size_[usage_index]; - } - resource_list->total_resource_usage_aliased_size[kRmtResourceUsageTypeFree] = unbound_size; + UpdateTotalResourceUsageAliasedSize(resource_list, memory_aliasing_calculator); } } - } - // track the bytes bound - resource_list->resource_usage_size[usage_type] += resource->size_in_bytes; + if ((track_user_data) && (resource->address == allocation->base_address)) + { + // Keep track of resources bound to a virtual allocation. + RmtResourceUserDataTrackBoundResource(resource, allocation->allocation_identifier); + } + } return kRmtOk; } @@ -984,8 +980,18 @@ RmtErrorCode RmtResourceUpdateAliasSize(const RmtResourceIdentifier resource_id, RmtResource* resource = FindResourceById(resource_list, resource_id); if (resource != nullptr) { - resource->adjusted_size_in_bytes = alias_size; - result = kRmtOk; + if (resource->resource_type == RmtResourceType::kRmtResourceTypeHeap) + { + // Heap resources are a special case. + // Overlapping resources are not considered when calculating heap memory adjusted for aliasing. + resource->adjusted_size_in_bytes = resource->size_in_bytes; + } + else + { + resource->adjusted_size_in_bytes = alias_size; + } + + result = kRmtOk; } return result; diff --git a/source/backend/rmt_resource_list.h b/source/backend/rmt_resource_list.h index beefa2a..57b8f79 100644 --- a/source/backend/rmt_resource_list.h +++ b/source/backend/rmt_resource_list.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Structures and functions for working with a resource list. @@ -166,15 +166,13 @@ typedef struct RmtResourceList RmtPool resource_id_node_pool; ///< The pool allocator for the memory buffer pointed to be resourceIdNodes. // Storage for resources. - RmtResource* resources; ///< A buffer of extra resource details. - int32_t resource_count; ///< The number of live resources in the list. - int32_t maximum_concurrent_resources; ///< The maximum number of resources that can be in flight at once. - const RmtVirtualAllocationList* virtual_allocation_list; ///< The virtual allocation to query for bindings. - - int32_t resource_usage_count[kRmtResourceUsageTypeCount]; ///< The number of each resource usage currently in the list. - uint64_t resource_usage_size[kRmtResourceUsageTypeCount]; - uint64_t total_resource_usage_aliased_size[kRmtResourceUsageTypeCount]; ///< Resource usage sizes for all resources in the list. - bool enable_aliased_resource_usage_sizes; ///< A flag used to indicate that, if true, aliased usage sizes are being calculated. + RmtResource* resources; ///< A buffer of extra resource details. + int32_t resource_count; ///< The number of live resources in the list. + int32_t maximum_concurrent_resources; ///< The maximum number of resources that can be in flight at once. + const RmtVirtualAllocationList* virtual_allocation_list; ///< The virtual allocation to query for bindings. + int32_t resource_usage_count[kRmtResourceUsageTypeCount]; ///< The number of each resource usage currently in the list. + uint64_t total_resource_usage_aliased_size[kRmtResourceUsageTypeCount]; ///< Resource usage sizes for all resources in the list. + bool enable_aliased_resource_usage_sizes; ///< A flag used to indicate that, if true, aliased usage sizes are being calculated. } RmtResourceList; @@ -223,7 +221,8 @@ RmtErrorCode RmtResourceListAddResourceCreate(RmtResourceList* resource_list, co /// /// @param [in] resource_list A pointer to a RmtResourceList structure. /// @param [in] resource_bind A pointer to a RmtTokenResourceBind structure. -/// +/// @param [in] track_user_data A flag that indicates, if true, that the bind needs to be tracked for user data processing. +/// /// @retval /// kRmtOk The operation completed successfully. /// @retval @@ -232,7 +231,7 @@ RmtErrorCode RmtResourceListAddResourceCreate(RmtResourceList* resource_list, co /// kRmtErrorNoResourceFound The operation failed because the resource in resource_bind can't be found. /// @retval /// kRmtErrorResourceAlreadyBound The operation failed because the resource in resource_bind is already bound. -RmtErrorCode RmtResourceListAddResourceBind(RmtResourceList* resource_list, const RmtTokenResourceBind* resource_bind); +RmtErrorCode RmtResourceListAddResourceBind(RmtResourceList* resource_list, const RmtTokenResourceBind* resource_bind, const bool track_user_data); /// Add a resource destroy to the list. /// diff --git a/source/backend/rmt_resource_userdata.cpp b/source/backend/rmt_resource_userdata.cpp index 960c9bd..a13085f 100644 --- a/source/backend/rmt_resource_userdata.cpp +++ b/source/backend/rmt_resource_userdata.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Function implementation for any resource userdata. @@ -9,19 +9,41 @@ #include "rmt_assert.h" #include "rmt_print.h" +#include "rmt_resource_list.h" #include "rmt_string_memory_pool.h" +#include "rmt_virtual_allocation_list.h" +#include #include #include #include #include +// Constant used when matching implicit resources to heaps. The creation times must be equal or less than this value to be considered a pair. +static const size_t kImplicitResourceCheckClockTicksThreshold = 2; + // Constant used to indicate an unknown driver resource ID. static const RmtResourceIdentifier kUnknownDriverResourceId = 0; // Constant used to indicate an unknown correlation ID. static const RmtCorrelationIdentifier kUnknownCorrelationId = 0; +// A structure that contains the information needed for matching a heap with an image or buffer resource. +typedef struct PairedResourceAndHeapInfo +{ + RmtResourceIdentifier heap_internal_resource_id; + RmtResourceIdentifier image_buffer_internal_resource_id; +} PairedResourceAndHeapInfo; + +// A map used to match an allocation with a heap or image/buffer resource using the allocation's unique ID. +std::unordered_map paired_resources_and_heaps; + +// A lookup map used to locate an image/buffer resource using a heap resource ID as the key. +std::unordered_map paired_heap_to_resource_map; + +// A lookup map used to locate a heap using an image/buffer resource ID as the key. +std::unordered_map paired_resource_to_heap_map; + // UserData related Token types enum TokenType { @@ -35,12 +57,13 @@ enum TokenType // A structure used to hold information about the tokens that are processed. struct TokenData { - TokenType token_type; - RmtResourceType resource_type; - RmtResourceIdentifier internal_resource_id; - RmtResourceIdentifier driver_resource_id; - RmtResourceIdentifier correlation_id; - char* resource_name; + TokenType token_type; + RmtResourceType resource_type; + RmtResourceIdentifier internal_resource_id; + RmtResourceIdentifier driver_resource_id; + RmtResourceIdentifier correlation_id; + char* resource_name; + RmtImplicitResourceType implicit_resource_type; }; // An ID used for tracking resource names. @@ -63,8 +86,8 @@ static std::unordered_map correlation_id_to_res // This is the one that sticks around. Map of resource id to string. This is used to patch everything up in after processing completes. static std::unordered_map internal_resource_id_to_resource_name; -// Set of implicit resources. -static std::unordered_set resource_identifier_implicit; +// Lookup map of implicit resources using an internal resource identifier as the key. +static std::unordered_map resource_identifier_implicit; // Set of resources needing correlations. static std::unordered_set internal_resource_ids_needing_correlation; @@ -78,6 +101,54 @@ static RmtStringMemoryPool resource_name_string_pool(kMemoryPoolBlockSize); // Flag indicating, if true, that Name UserData tokens have been parsed. static bool resource_name_token_tracked = false; +// @brief Stores an implicit resource in a map. +// +// If the resource being stored is an image or buffer and the implicit resource type is implicit heap then a search is performed to locate a heap resource that +// matches the buffer resource's virtual address. If a matching heap resource is found, the heap resource ID is stored in the implicit +// resource list instead of the buffer resource's ID. +// +// If the resource being stored is a buffer and the implicit resource type is implicit resource then it is stored in the implicit resource list (there +// is no need to match it with a heap resource). +// +// If the image/buffer resource's ID was previously stored in the implicit resource list, it is marked unused (this indicates an unused duplicate token was generated). +static void StoreImplicitResource(const RmtResourceIdentifier internal_resource_id, const RmtImplicitResourceType implicit_resource_type) +{ + // Set a flag to true if a token was previously processed with this same resource ID. + const auto& previous_implicit_resource_iterator = resource_identifier_implicit.find(internal_resource_id); + const bool previous_implicit_resource_found = previous_implicit_resource_iterator != resource_identifier_implicit.end(); + const auto& heap_lookup_iterator = paired_resource_to_heap_map.find(internal_resource_id); + + // Check for implicit image/buffer resource (also, make sure a duplicate hasn't already been stored in the resource_identifier_implicit map). + if ((implicit_resource_type == RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitResource) && !previous_implicit_resource_found) + { + // Only store this resource ID if a paired heap wasn't already marked implicit. This is a workaround in case there are multiple + // MarkResourceImplicit UserData tokens for this resource originating from ETW. If a token with an kRmtImplicitResourceTypeImplicitHeap + // type is processed, ignore any other tokens with the kRmtImplicitResourceTypeImplicitResource type. + if ((heap_lookup_iterator == paired_resource_to_heap_map.end()) || !(RmtResourceUserDataIsResourceImplicit(heap_lookup_iterator->second))) + { + // Store this ID in the list of implicit resources. + // Note: This maybe updated later if a duplicate MarkImplicitResource token is processed with this same resource ID. + resource_identifier_implicit[internal_resource_id] = RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitResource; + } + } + else if (implicit_resource_type == RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitHeap) + { + // Find the heap associated with this resource and add its resource ID to the implicit resource map. + if (heap_lookup_iterator != paired_resource_to_heap_map.end()) + { + const RmtResourceIdentifier heap_resource_id = heap_lookup_iterator->second; + resource_identifier_implicit[heap_resource_id] = implicit_resource_type; + + // Workaround for duplicate MarkImplicitResource UserData tokens: If the buffer resource associated with this implicit heap was already + // marked implicit, change the buffer resource's implicit type to unused since the heap and buffer resource can't both be implicit. + if (previous_implicit_resource_found) + { + resource_identifier_implicit[internal_resource_id] = RmtImplicitResourceType::kRmtImplicitResourceTypeUnused; + } + } + } +} + static RmtResourceNameHash ResourceNamingGenerateHash(RmtResourceIdentifier resource_id, RmtCorrelationIdentifier correlation_id) { RMT_ASSERT((resource_id != kUnknownDriverResourceId) || (correlation_id != kUnknownCorrelationId)); @@ -241,7 +312,7 @@ static void ProcessImplicitResourceToken(const TokenData& token_data, bool any_c if (internal_resource_ids_needing_correlation.find(internal_resource_identifier) == internal_resource_ids_needing_correlation.end()) { // Mark this resource as implicit. - resource_identifier_implicit.insert(internal_resource_identifier); + StoreImplicitResource(internal_resource_identifier, token_data.implicit_resource_type); return; } } @@ -257,7 +328,7 @@ static void ProcessImplicitResourceToken(const TokenData& token_data, bool any_c { // The internal resource ID was found. Mark this resource as implicit. const RmtResourceIdentifier internal_resource_identifier = (*internal_resource_id_iterator2).second; - resource_identifier_implicit.insert(internal_resource_identifier); + StoreImplicitResource(internal_resource_identifier, token_data.implicit_resource_type); } } } @@ -272,7 +343,7 @@ static void ProcessImplicitResourceToken(const TokenData& token_data, bool any_c { // The internal resource ID was found. Mark this resource as implicit. const RmtResourceIdentifier internal_resource_identifier = (*it).second; - resource_identifier_implicit.insert(internal_resource_identifier); + StoreImplicitResource(internal_resource_identifier, token_data.implicit_resource_type); } } } @@ -314,6 +385,7 @@ RmtErrorCode RmtResourceUserdataProcessEvents(const bool any_correlations) internal_resource_id_to_resource_hash_id.clear(); correlation_id_to_resource_name.clear(); internal_resource_ids_needing_correlation.clear(); + paired_resources_and_heaps.clear(); tokens.clear(); // Clear the flag that indicates there are Name UserData tokens waiting to be processed. @@ -409,19 +481,69 @@ RmtErrorCode RmtResourceUserdataTrackResourceNameToken(const RmtCorrelationIdent return result; } -RmtErrorCode RmtResourceUserdataTrackImplicitResourceToken(RmtResourceIdentifier correlation_id, uint64_t timestamp, uint64_t delay_time) +RmtErrorCode RmtResourceUserdataTrackImplicitResourceToken(const RmtResourceIdentifier correlation_id, + const uint64_t timestamp, + const uint64_t delay_time, + const RmtImplicitResourceType implicit_resource_type) { if (timestamp - delay_time <= timestamp) { - TokenData token_data = {}; - token_data.token_type = kResourceImplicit; - token_data.correlation_id = correlation_id; + TokenData token_data = {}; + token_data.token_type = kResourceImplicit; + token_data.correlation_id = correlation_id; + token_data.implicit_resource_type = implicit_resource_type; + tokens.insert(std::make_pair(timestamp - delay_time, token_data)); return kRmtOk; } return kRmtErrorMalformedData; } +RmtErrorCode RmtResourceUserDataTrackBoundResource(const RmtResource* resource, const uint64_t allocation_identifier) +{ + RMT_RETURN_ON_ERROR(resource != nullptr, kRmtErrorInvalidPointer); + + auto paired_heap_and_resource_info = paired_resources_and_heaps.find(allocation_identifier); + if (resource->resource_type == RmtResourceType::kRmtResourceTypeHeap) + { + const RmtResource* heap_resource = resource; + if (paired_heap_and_resource_info == paired_resources_and_heaps.end()) + { + // A matching image/buffer hasn't been processed yet. Just store the heap info for now. + paired_resources_and_heaps[allocation_identifier].heap_internal_resource_id = heap_resource->identifier; + } + else + { + // Heap is paired with resource. Update lookup tables. + paired_resource_to_heap_map[paired_heap_and_resource_info->second.image_buffer_internal_resource_id] = heap_resource->identifier; + paired_heap_to_resource_map[heap_resource->identifier] = paired_heap_and_resource_info->second.image_buffer_internal_resource_id; + + // Remove from paired resources and heaps since a match has been found. + paired_resources_and_heaps.erase(allocation_identifier); + } + } + else if ((resource->resource_type == RmtResourceType::kRmtResourceTypeBuffer) || (resource->resource_type == RmtResourceType::kRmtResourceTypeImage)) + { + const RmtResource* image_buffer_resource = resource; + if (paired_heap_and_resource_info == paired_resources_and_heaps.end()) + { + // A matching heap hasn't been processed yet. Just store the image/buffer resource info for now. + paired_resources_and_heaps[allocation_identifier].image_buffer_internal_resource_id = image_buffer_resource->identifier; + } + else + { + // Heap is paired with an image/buffer resource. + paired_heap_to_resource_map[paired_heap_and_resource_info->second.heap_internal_resource_id] = image_buffer_resource->identifier; + paired_resource_to_heap_map[image_buffer_resource->identifier] = paired_heap_and_resource_info->second.heap_internal_resource_id; + + // Remove from paired resources and heaps since a match has been found. + paired_resources_and_heaps.erase(allocation_identifier); + } + } + + return kRmtOk; +} + RmtErrorCode RmtResourceUserdataGetResourceName(const RmtResourceIdentifier resource_id, const char** out_resource_name) { RMT_RETURN_ON_ERROR(out_resource_name != nullptr, kRmtErrorInvalidPointer); @@ -460,9 +582,55 @@ RmtErrorCode RmtResourceUserdataUpdateResourceName(const RmtResourceList* resour bool RmtResourceUserDataIsResourceImplicit(const RmtResourceIdentifier resource_id) { - if (resource_identifier_implicit.find(resource_id) != resource_identifier_implicit.end()) + const auto implicit_resource_info = resource_identifier_implicit.find(resource_id); + if (implicit_resource_info != resource_identifier_implicit.end()) { - return true; + if ((implicit_resource_info->second == RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitHeap) || + (implicit_resource_info->second == RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitResource)) + { + return true; + } } return false; } + +RmtErrorCode RmtResourceUserDataFindPairedResource(const RmtResourceIdentifier internal_resource_id, RmtResourceIdentifier* out_paired_internal_resource_id) +{ + RmtErrorCode result = kRmtErrorNoResourceFound; + const auto& heap_resource_iterator = paired_resource_to_heap_map.find(internal_resource_id); + if (heap_resource_iterator != paired_resource_to_heap_map.end()) + { + *out_paired_internal_resource_id = heap_resource_iterator->second; + result = kRmtOk; + } + else + { + const auto& image_buffer_resource_iterator = paired_heap_to_resource_map.find(internal_resource_id); + if (image_buffer_resource_iterator != paired_heap_to_resource_map.end()) + { + *out_paired_internal_resource_id = image_buffer_resource_iterator->second; + result = kRmtOk; + } + } + + return result; +} + +void RmtResourceUserDataCleanup() +{ + // Clear temporary lookup maps (in case processing fails before loading the trace file completes). + correlation_id_to_resource_hash.clear(); + resource_hash_to_correlation_id.clear(); + resource_hash_to_internal_resource_id.clear(); + internal_resource_id_to_resource_hash_id.clear(); + correlation_id_to_resource_name.clear(); + internal_resource_ids_needing_correlation.clear(); + paired_resources_and_heaps.clear(); + tokens.clear(); + + // Clear lookup maps used after the trace file has been processed. + resource_identifier_implicit.clear(); + internal_resource_id_to_resource_name.clear(); + paired_heap_to_resource_map.clear(); + paired_resource_to_heap_map.clear(); +} diff --git a/source/backend/rmt_resource_userdata.h b/source/backend/rmt_resource_userdata.h index e6d375f..7de474b 100644 --- a/source/backend/rmt_resource_userdata.h +++ b/source/backend/rmt_resource_userdata.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Function definitions for any resource sideband data. @@ -82,7 +82,7 @@ RmtErrorCode RmtResourceUserdataTrackResourceNameToken(const RmtCorrelationIdent const RmtTimestamp delay_time); /// @brief Lookup the name associated with a resource and update the resource object. - +/// /// @param [in] resource_list A pointer to the list of resource objects. /// @param [in] internal_resource_id The internal resource identifier of the resource to be updated. /// @@ -99,12 +99,27 @@ RmtErrorCode RmtResourceUserdataUpdateResourceName(const RmtResourceList* resour /// @param [in] correlation_id The correlation ID. /// @param [in] timestamp The timestamp for the token. /// @param [in] delay_time The delay between when the data for the token was generated and when the token was emitted. +/// @param [in] implicit_resource_type The type of implicit resource. /// /// @retval /// kRmtOk The operation completed successfully. /// @retval /// kRmtErrorMalformedData An invalid delay_time was specified. -RmtErrorCode RmtResourceUserdataTrackImplicitResourceToken(RmtResourceIdentifier correlation_id, uint64_t timestamp, uint64_t delay_time); +RmtErrorCode RmtResourceUserdataTrackImplicitResourceToken(const RmtResourceIdentifier correlation_id, + const uint64_t timestamp, + const uint64_t delay_time, + const RmtImplicitResourceType implicit_resource_type); + +/// @brief Track when a resource is bound to an allocation. +/// +/// @param [in] resource A pointer to a resource object. +/// @param [in] allocation_identifier A unique identifier for the allocation this resource is bound to. +/// +/// @retval +/// kRmtOk The operation completed successfully. +/// @retval +/// kRmtErrorInvalidPointer The resource pointer is invalid. +RmtErrorCode RmtResourceUserDataTrackBoundResource(const RmtResource* resource, const uint64_t allocation_identifier); /// @brief Retrieve the resource name associated with a resource. /// @@ -126,7 +141,24 @@ RmtErrorCode RmtResourceUserdataGetResourceName(const RmtResourceIdentifier inte /// @returns true if resource is implicit, false otherwise. bool RmtResourceUserDataIsResourceImplicit(const RmtResourceIdentifier resource_id); +/// @brief Retrieve the resource ID for a paired heap or image/buffer resource. +/// +/// @param [in] internal_resource_id The resource identifier to match against. +/// @param [out] out_paired_internal_resource_id The resource identifier of the paired heap or image/buffer resource. +/// +/// @retval +/// kRmtOk The operation completed successfully. +/// @retval +/// kRmtErrorInvalidPointer The out_heap_internal_resource_id pointer is invalid. +/// @retval +/// kRmtErrorResourceNotFound A resource could not be found for the internal_resource_id specified. +RmtErrorCode RmtResourceUserDataFindPairedResource(const RmtResourceIdentifier internal_resource_id, RmtResourceIdentifier* out_paired_internal_resource_id); + +/// @brief Clear internal UserData lookup maps. +/// +void RmtResourceUserDataCleanup(); + #ifdef __cplusplus } #endif // #ifdef __cplusplus -#endif // #ifndef RMV_BACKEND_RMT_RESOURCE_USERDATA_H_ +#endif // #ifndef RMV_BACKEND_RMT_RESOURCE_USERDATA_H_ \ No newline at end of file diff --git a/source/backend/rmt_segment_info.h b/source/backend/rmt_segment_info.h index 947935d..caaf379 100644 --- a/source/backend/rmt_segment_info.h +++ b/source/backend/rmt_segment_info.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief The segment information captured for the target process. diff --git a/source/backend/rmt_snapshot_writer.cpp b/source/backend/rmt_snapshot_writer.cpp index 47d9905..aa81984 100644 --- a/source/backend/rmt_snapshot_writer.cpp +++ b/source/backend/rmt_snapshot_writer.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the base class that handles writing snapshot data. diff --git a/source/backend/rmt_snapshot_writer.h b/source/backend/rmt_snapshot_writer.h index 4359af9..d0725a6 100644 --- a/source/backend/rmt_snapshot_writer.h +++ b/source/backend/rmt_snapshot_writer.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Base class that handles writing snapshot data. diff --git a/source/backend/rmt_thread.cpp b/source/backend/rmt_thread.cpp index 6968ccf..ac61ec9 100644 --- a/source/backend/rmt_thread.cpp +++ b/source/backend/rmt_thread.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of platform-specific thread. diff --git a/source/backend/rmt_thread.h b/source/backend/rmt_thread.h index 92a670f..05e5590 100644 --- a/source/backend/rmt_thread.h +++ b/source/backend/rmt_thread.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Abstraction of a thread. diff --git a/source/backend/rmt_thread_event.cpp b/source/backend/rmt_thread_event.cpp index 5558b24..d2633e4 100644 --- a/source/backend/rmt_thread_event.cpp +++ b/source/backend/rmt_thread_event.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of platform-specific thread events. @@ -12,7 +12,7 @@ #define WIN32_LEAN_AND_MEAN #include #else -#include "../third_party/pevents/pevents.h" +#include "pevents/src/pevents.h" #endif // #ifdef _WIN32 // structure for thread event diff --git a/source/backend/rmt_thread_event.h b/source/backend/rmt_thread_event.h index 2df5f77..f18edc2 100644 --- a/source/backend/rmt_thread_event.h +++ b/source/backend/rmt_thread_event.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of platform-specific thread events. diff --git a/source/backend/rmt_trace_loader.cpp b/source/backend/rmt_trace_loader.cpp index e1bccb4..d61448c 100644 --- a/source/backend/rmt_trace_loader.cpp +++ b/source/backend/rmt_trace_loader.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Trace loader structures and functions. @@ -56,7 +56,7 @@ RmtErrorCode RmtTraceLoaderTraceLoad(const char* trace_file_name) } // Create the default timeline for the data set. - error_code = RmtDataSetGenerateTimeline(&data_set_, kRmtDataTimelineTypeCommitted, &timeline_); + error_code = RmtDataSetGenerateTimeline(&data_set_, kRmtDataTimelineTypeVirtualMemory, &timeline_); return error_code; } diff --git a/source/backend/rmt_trace_loader.h b/source/backend/rmt_trace_loader.h index efd1f7e..4411cb1 100644 --- a/source/backend/rmt_trace_loader.h +++ b/source/backend/rmt_trace_loader.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Trace loader structures and functions. diff --git a/source/backend/rmt_virtual_allocation_list.cpp b/source/backend/rmt_virtual_allocation_list.cpp index 75dd930..9c133b2 100644 --- a/source/backend/rmt_virtual_allocation_list.cpp +++ b/source/backend/rmt_virtual_allocation_list.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the virtual allocation list functions. @@ -327,19 +327,19 @@ uint64_t RmtVirtualAllocationGetTotalUnboundSpaceInAllocation(const RmtDataSnaps uint64_t RmtVirtualAllocationGetAverageResourceSizeInBytes(const RmtDataSnapshot* snapshot, const RmtVirtualAllocation* virtual_allocation) { RMT_ASSERT(virtual_allocation); - if (virtual_allocation == NULL || virtual_allocation->resource_count == 0) + if (virtual_allocation == NULL || virtual_allocation->non_heap_resource_count == 0) { return 0; } const uint64_t total_resource_size = RmtVirtualAllocationGetTotalResourceMemoryInBytes(snapshot, virtual_allocation); - return total_resource_size / virtual_allocation->resource_count; + return total_resource_size / virtual_allocation->non_heap_resource_count; } uint64_t RmtVirtualAllocationGetResourceStandardDeviationInBytes(const RmtDataSnapshot* snapshot, const RmtVirtualAllocation* virtual_allocation) { RMT_ASSERT(virtual_allocation); - if (virtual_allocation == NULL || virtual_allocation->resource_count == 0) + if (virtual_allocation == NULL || virtual_allocation->non_heap_resource_count == 0) { return 0; } @@ -348,10 +348,18 @@ uint64_t RmtVirtualAllocationGetResourceStandardDeviationInBytes(const RmtDataSn int64_t avg_resource_size = RmtVirtualAllocationGetAverageResourceSizeInBytes(snapshot, virtual_allocation); for (int32_t current_resource_index = 0; current_resource_index < virtual_allocation->resource_count; ++current_resource_index) { - const int64_t diff = virtual_allocation->resources[current_resource_index]->size_in_bytes - avg_resource_size; + const RmtResource* current_resource = virtual_allocation->resources[current_resource_index]; + + if (current_resource->resource_type == RmtResourceType::kRmtResourceTypeHeap) + { + // Skip heaps. + continue; + } + + const int64_t diff = current_resource->size_in_bytes - avg_resource_size; variance = diff * diff; } - variance /= virtual_allocation->resource_count; + variance /= virtual_allocation->non_heap_resource_count; return (uint64_t)sqrt((double)variance); } @@ -485,7 +493,7 @@ RmtErrorCode RmtVirtualAllocationListAddAllocation(RmtVirtualAllocationList* vir const RmtGpuAddress hashed_address = HashGpuAddress(address); AddAllocationToTree(virtual_allocation_list, hashed_address, size_in_4kb_pages, allocation_details); - const uint64_t size_in_bytes = (size_in_4kb_pages << 12); + const uint64_t size_in_bytes = (static_cast(size_in_4kb_pages) << 12); virtual_allocation_list->total_allocated_bytes += size_in_bytes; virtual_allocation_list->allocations_per_preferred_heap[allocation_details->heap_preferences[0]] += size_in_bytes; return kRmtOk; @@ -516,7 +524,7 @@ RmtErrorCode RmtVirtualAllocationListRemoveAllocation(RmtVirtualAllocationList* current_allocation_interval->dead = 1; current_allocation_interval->allocation->flags |= kRmtAllocationDetailIsDead; - const uint64_t size_in_bytes = current_allocation_interval->allocation->size_in_4kb_page << 12; + const uint64_t size_in_bytes = static_cast(current_allocation_interval->allocation->size_in_4kb_page) << 12; virtual_allocation_list->total_allocated_bytes -= size_in_bytes; virtual_allocation_list->allocations_per_preferred_heap[current_allocation_interval->allocation->heap_preferences[0]] -= size_in_bytes; @@ -825,11 +833,6 @@ static RmtErrorCode TrackResourceAdd(const RmtResource* resource, std::mapidentifier) == true) diff --git a/source/backend/rmt_virtual_allocation_list.h b/source/backend/rmt_virtual_allocation_list.h index af7aa70..09e088f 100644 --- a/source/backend/rmt_virtual_allocation_list.h +++ b/source/backend/rmt_virtual_allocation_list.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Structures and functions for managing a virtual allocation list. @@ -64,9 +64,10 @@ typedef struct RmtVirtualAllocation int32_t next_resource_index; ///< The index of the new resource. RmtMemoryRegion* unbound_memory_regions; ///< An array of RmtUnboundMemoryRegion structures representing the unbound memory inside this virtual allocation. - int32_t unbound_memory_region_count; ///< The number of RmtUnboundMemoryRegion structures inside unboundMemoryRegions. - uint64_t allocation_identifier; ///< Uniquely identifies this virtual memory allocation. - uint64_t resource_usage_aliased_size[kRmtResourceUsageTypeCount]; ///< Aliased resource usage sizes for resource bound to this allocation. + int32_t unbound_memory_region_count; ///< The number of RmtUnboundMemoryRegion structures inside unboundMemoryRegions. + uint64_t allocation_identifier; ///< Uniquely identifies this virtual memory allocation. + uint64_t resource_usage_aliased_size[kRmtResourceUsageTypeCount]; ///< Aliased resource usage sizes for resource bound to this allocation. + const char* name; ///< Allocation name. } RmtVirtualAllocation; diff --git a/source/backend/rmt_warnings.h b/source/backend/rmt_warnings.h index a6c8e23..47eb54d 100644 --- a/source/backend/rmt_warnings.h +++ b/source/backend/rmt_warnings.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of structures and functions for RMT warnings. diff --git a/source/frontend/CMakeLists.txt b/source/frontend/CMakeLists.txt index b774ef4..c42c889 100644 --- a/source/frontend/CMakeLists.txt +++ b/source/frontend/CMakeLists.txt @@ -1,3 +1,8 @@ +####################################################################################################################### +### Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. +### \author AMD Developer Tools Team +####################################################################################################################### + cmake_minimum_required(VERSION 3.11) project(RadeonMemoryVisualizer) @@ -40,6 +45,7 @@ ENDIF(UNIX) # List of all source files. It may be possible to have the build process call cmake to update the makefiles # only when this file has changed (ie source files have been added or removed) + set( SOURCES "main.cpp" "managers/load_animation_manager.cpp" @@ -186,8 +192,12 @@ set( SOURCES "views/custom_widgets/rmv_delta_display.h" "views/custom_widgets/rmv_delta_display_widget.cpp" "views/custom_widgets/rmv_delta_display_widget.h" + "views/custom_widgets/rmv_fixed_width_label.cpp" + "views/custom_widgets/rmv_fixed_width_label.h" "views/custom_widgets/rmv_heap_overview_memory_bar.cpp" "views/custom_widgets/rmv_heap_overview_memory_bar.h" + "views/custom_widgets/rmv_range_slider.cpp" + "views/custom_widgets/rmv_range_slider.h" "views/custom_widgets/rmv_resource_details.cpp" "views/custom_widgets/rmv_resource_details.h" "views/custom_widgets/rmv_resource_timeline.cpp" @@ -294,6 +304,7 @@ set( WINDOWS_SOURCES "windows/rmv_icon.ico" ) + # Filter out the UI files and get the list of generated files set(UI_FILES ${SOURCES}) list(FILTER UI_FILES INCLUDE REGEX "\.ui$") @@ -385,6 +396,7 @@ IF(WIN32) COMMAND ${CMAKE_COMMAND} -E copy_if_different ${VSREDISTDIR}/vcruntime140_1.dll $ ) + # Add the Debug-Only custom commands. # This functionality requires CMake 3.8 or higher. add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD @@ -421,3 +433,4 @@ IF(UNIX AND NOT APPLE) ENDIF(UNIX AND NOT APPLE) devtools_target_options(${PROJECT_NAME}) + diff --git a/source/frontend/main.cpp b/source/frontend/main.cpp index eb89bde..f6451c7 100644 --- a/source/frontend/main.cpp +++ b/source/frontend/main.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Main entry point. diff --git a/source/frontend/managers/load_animation_manager.cpp b/source/frontend/managers/load_animation_manager.cpp index b8763ed..91dd2fc 100644 --- a/source/frontend/managers/load_animation_manager.cpp +++ b/source/frontend/managers/load_animation_manager.cpp @@ -1,5 +1,5 @@ //============================================================================== -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the file loading animation manager. @@ -26,7 +26,6 @@ namespace rmv LoadAnimationManager::LoadAnimationManager(QObject* parent) : QObject(parent) , tab_widget_(nullptr) - , file_menu_(nullptr) , file_load_animation_(nullptr) { } @@ -35,10 +34,9 @@ namespace rmv { } - void LoadAnimationManager::Initialize(TabWidget* tab_widget, QMenu* file_menu) + void LoadAnimationManager::Initialize(TabWidget* tab_widget) { tab_widget_ = tab_widget; - file_menu_ = file_menu; } void LoadAnimationManager::ResizeAnimation() @@ -62,7 +60,6 @@ namespace rmv file_load_animation_->show(); tab_widget_->setDisabled(true); - file_menu_->setDisabled(true); emit rmv::MessageManager::Get().ChangeActionsRequested(false); qApp->setOverrideCursor(Qt::BusyCursor); @@ -87,7 +84,6 @@ namespace rmv file_load_animation_ = nullptr; tab_widget_->setEnabled(true); - file_menu_->setEnabled(true); emit rmv::MessageManager::Get().ChangeActionsRequested(true); qApp->restoreOverrideCursor(); diff --git a/source/frontend/managers/load_animation_manager.h b/source/frontend/managers/load_animation_manager.h index b31d371..1c7c7de 100644 --- a/source/frontend/managers/load_animation_manager.h +++ b/source/frontend/managers/load_animation_manager.h @@ -1,5 +1,5 @@ //============================================================================== -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Class definition for the file loading animation manager. @@ -44,8 +44,7 @@ namespace rmv /// @brief Initialize the animation manager. /// /// @param [in] tab_widget The tab widget from the main window. - /// @param [in] file_menu The file menu widget from the main window. - void Initialize(TabWidget* tab_widget, QMenu* file_menu); + void Initialize(TabWidget* tab_widget); /// @brief Start the loading animation. /// diff --git a/source/frontend/managers/message_manager.cpp b/source/frontend/managers/message_manager.cpp index 5a4f562..d4faaf2 100644 --- a/source/frontend/managers/message_manager.cpp +++ b/source/frontend/managers/message_manager.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the MessageManager class. diff --git a/source/frontend/managers/message_manager.h b/source/frontend/managers/message_manager.h index e758eba..123f755 100644 --- a/source/frontend/managers/message_manager.h +++ b/source/frontend/managers/message_manager.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Declaration for the MessageManager. @@ -61,12 +61,15 @@ namespace rmv /// @param [in] pane The pane to navigate to. void PaneSwitchRequested(rmv::RMVPaneId pane); + /// @brief Signal to requested that snapshots be switched (from the Snapshot delta pane). + void SwapSnapshotsRequested(); + /// @brief Signal for when the hash values changed. void HashesChanged(); /// @brief Signal to request enabling or disabling UI actions. /// - /// @param [in] enable If true, actions should be enabled. Otherwise, actions should be disabled. + /// @param [in] enable If true, actions should be enabled. Otherwise, actions should be disabled. void ChangeActionsRequested(const bool enable); }; } // namespace rmv diff --git a/source/frontend/managers/navigation_manager.cpp b/source/frontend/managers/navigation_manager.cpp index 61e5f60..d7d8f77 100644 --- a/source/frontend/managers/navigation_manager.cpp +++ b/source/frontend/managers/navigation_manager.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for back/fwd navigation manager. diff --git a/source/frontend/managers/navigation_manager.h b/source/frontend/managers/navigation_manager.h index 3204509..a2dd4e6 100644 --- a/source/frontend/managers/navigation_manager.h +++ b/source/frontend/managers/navigation_manager.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for back/fwd navigation manager. diff --git a/source/frontend/managers/pane_manager.cpp b/source/frontend/managers/pane_manager.cpp index ae6a32d..5f8f943 100644 --- a/source/frontend/managers/pane_manager.cpp +++ b/source/frontend/managers/pane_manager.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the pane manager. diff --git a/source/frontend/managers/pane_manager.h b/source/frontend/managers/pane_manager.h index 617f1db..5dc0204 100644 --- a/source/frontend/managers/pane_manager.h +++ b/source/frontend/managers/pane_manager.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the pane manager. diff --git a/source/frontend/managers/snapshot_manager.cpp b/source/frontend/managers/snapshot_manager.cpp index 882deb4..c344527 100644 --- a/source/frontend/managers/snapshot_manager.cpp +++ b/source/frontend/managers/snapshot_manager.cpp @@ -1,5 +1,5 @@ //============================================================================== -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Snapshot Manager. @@ -110,8 +110,6 @@ namespace rmv , selected_compared_snapshots_{} , loaded_snapshot_(nullptr) , loaded_compared_snapshots_{} - , resource_thresholds_{} - , unbound_resource_thresholds_{} , resource_identifier_(0) { } @@ -348,51 +346,8 @@ namespace rmv void SnapshotManager::CacheResourceData() { // Snapshot is loaded at this point. - // Deselect any selected resource. - memset(resource_thresholds_, 0, sizeof(uint64_t) * (rmv::kSizeSliderRange + 1)); - memset(unbound_resource_thresholds_, 0, sizeof(uint64_t) * (rmv::kSizeSliderRange + 1)); - RmtDataSnapshot* snapshot = rmv::SnapshotManager::Get().GetOpenSnapshot(); - std::vector resource_sizes; - - const RmtResourceList& resource_list = snapshot->resource_list; - int resource_count = resource_list.resource_count; - if (resource_count > 0) - { - // Build a list of all resources and calculate the size thresholds for the resource size slider. - for (int loop = 0; loop < resource_count; loop++) - { - const RmtResource& resource = resource_list.resources[loop]; - const uint64_t size = resource.adjusted_size_in_bytes; - if (size > 0) - { - resource_sizes.push_back(size); - } - } - rmv_util::BuildResourceSizeThresholds(resource_sizes, resource_thresholds_); - - // Add unbound resources to the existing resource list so it will contain bound and unbound resources. - // Recompute the size thresholds for the resource size slider. - int32_t allocation_count = snapshot->virtual_allocation_list.allocation_count; - for (int32_t current_virtual_allocation_index = 0; current_virtual_allocation_index < allocation_count; ++current_virtual_allocation_index) - { - const RmtVirtualAllocation* current_virtual_allocation = - &snapshot->virtual_allocation_list.allocation_details[current_virtual_allocation_index]; - - int32_t unbound_region_count = current_virtual_allocation->unbound_memory_region_count; - for (int32_t unbound_region_index = 0; unbound_region_index < unbound_region_count; ++unbound_region_index) - { - uint64_t size = current_virtual_allocation->unbound_memory_regions[unbound_region_index].size; - if (size > 0) - { - resource_sizes.push_back(size); - } - } - } - rmv_util::BuildResourceSizeThresholds(resource_sizes, unbound_resource_thresholds_); - } - const RmtVirtualAllocationList& allocation_list = snapshot->virtual_allocation_list; const int32_t allocation_count = allocation_list.allocation_count; alias_model_.Clear(); @@ -405,18 +360,6 @@ namespace rmv } } - uint64_t SnapshotManager::GetSizeFilterThreshold(int32_t index, bool include_unbound_resources) const - { - if (include_unbound_resources) - { - return unbound_resource_thresholds_[index]; - } - else - { - return resource_thresholds_[index]; - } - } - const rmv::AliasedResourceModel& SnapshotManager::GetAliasModel() const { return alias_model_; diff --git a/source/frontend/managers/snapshot_manager.h b/source/frontend/managers/snapshot_manager.h index 31edd84..18f9c16 100644 --- a/source/frontend/managers/snapshot_manager.h +++ b/source/frontend/managers/snapshot_manager.h @@ -1,5 +1,5 @@ //============================================================================== -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Class definition for the Snapshot Manager. @@ -153,18 +153,6 @@ namespace rmv /// @brief Clear the opened snapshot. void ClearOpenSnapshot(); - /// @brief Get the 'filter by size' value based on where the slider is. - /// - /// The filtering used by the 'filter by size' slider is non-linear so this uses a - /// lookup to get the threshold values used to compare the resource sizes depending - /// on where the slider value is. - /// - /// @param [in] index The index position of the slider. - /// @param [in] include_unbound_resources If true, include unbound resources. - /// - /// @return The value of the filter threshold used for comparison. - uint64_t GetSizeFilterThreshold(int32_t index, bool include_unbound_resources = false) const; - /// @brief Get the model responsible for managing resource aliasing. /// /// @return The alias model. @@ -268,12 +256,9 @@ namespace rmv RmtSnapshotPoint* selected_compared_snapshots_[kSnapshotCompareCount]; ///< The compare snapshots selected in the snapshot table. RmtDataSnapshot* loaded_snapshot_; ///< A pointer to the currently opened (loaded) snapshot. RmtDataSnapshot* loaded_compared_snapshots_[kSnapshotCompareCount]; ///< Pointers to the currently opened (loaded) snapshots being compared. - uint64_t resource_thresholds_[rmv::kSizeSliderRange + 1]; ///< A list of resource size thresholds for the filter by size sliders. - uint64_t unbound_resource_thresholds_[rmv::kSizeSliderRange + - 1]; ///< A list of resource size thresholds including unbound resources, for the filter by size sliders. - rmv::AliasedResourceModel alias_model_; ///< The model used for showing aliased resources. - RmtResourceIdentifier resource_identifier_; ///< The resource to select when opening the snapshot. + rmv::AliasedResourceModel alias_model_; ///< The model used for showing aliased resources. + RmtResourceIdentifier resource_identifier_; ///< The resource to select when opening the snapshot. }; } // namespace rmv -#endif // RMV_MANAGERS_SNAPSHOT_MANAGER_H_ +#endif // RMV_MANAGERS_SNAPSHOT_MANAGER_H_ \ No newline at end of file diff --git a/source/frontend/managers/trace_manager.cpp b/source/frontend/managers/trace_manager.cpp index ac8617a..b784285 100644 --- a/source/frontend/managers/trace_manager.cpp +++ b/source/frontend/managers/trace_manager.cpp @@ -1,5 +1,5 @@ //============================================================================== -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Trace Manager. @@ -100,6 +100,10 @@ namespace rmv { return kTraceLoadReturnOutOfVirtualGPUMemory; } + else if (return_code == kRmtErrorTraceFileNotSupported) + { + return kTraceLoadReturnFileNotSupported; + } return kTraceLoadReturnFail; } @@ -212,24 +216,40 @@ namespace rmv if (error_code != kTraceLoadReturnSuccess) { - // If the trace file doesn't exist, ask the user if they want to remove it from - // the recent traces list. This has to be done from the main thread. + // If there's an error loading the trace and it is already in the recent traces list, + // ask the user if they want to remove it. This has to be done from the main thread. QFileInfo file_info(active_trace_path_); - QString text(""); + QString text(rmv::text::kOpenTraceErrorText.arg(file_info.fileName())); if (error_code == kTraceLoadReturnOutOfVirtualGPUMemory) { text += rmv::text::kOpenTraceOutOfVirtualGPUMemory; } + else if (error_code == kTraceLoadReturnFileNotSupported) + { + text += rmv::text::kOpenTraceFileNotSupported; + } - text += rmv::text::kDeleteRecentTraceText.arg(file_info.fileName()); + if (RMVSettings::Get().DoesFileExistInRecentList(active_trace_path_.toStdString().c_str())) + { + text += rmv::text::kDeleteRecentTraceText; - const int ret = - QtCommon::QtUtils::ShowMessageBox(parent_, QMessageBox::Yes | QMessageBox::No, QMessageBox::Question, rmv::text::kDeleteRecentTraceTitle, text); + const int ret = QtCommon::QtUtils::ShowMessageBox( + parent_, QMessageBox::Yes | QMessageBox::No, QMessageBox::Question, rmv::text::kDeleteRecentTraceTitle, text); - if (ret == QMessageBox::Yes) + if (ret == QMessageBox::Yes) + { + // Remove the file from the recent file list. + RMVSettings::Get().TraceLoaded(active_trace_path_.toLatin1().data(), nullptr, true); + RMVSettings::Get().SaveSettings(); + + // Notify the view to refresh the list. + emit TraceOpenFailed(); + } + } + else { - remove_from_list = true; + QtCommon::QtUtils::ShowMessageBox(parent_, QMessageBox::Ok, QMessageBox::Warning, rmv::text::kOpenTraceErrorTitle, text); } } @@ -251,7 +271,6 @@ namespace rmv } } rmv::LoadAnimationManager::Get().StopAnimation(); - disconnect(this, &TraceManager::TraceLoadThreadFinished, this, &TraceManager::FinalizeTraceLoading); // Defer deleting of this object until later, in case the thread is still executing something diff --git a/source/frontend/managers/trace_manager.h b/source/frontend/managers/trace_manager.h index ab922d8..3fdb8be 100644 --- a/source/frontend/managers/trace_manager.h +++ b/source/frontend/managers/trace_manager.h @@ -1,5 +1,5 @@ //============================================================================== -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Class definition for the Trace Manager. @@ -24,6 +24,7 @@ enum TraceLoadReturnCode kTraceLoadReturnError, kTraceLoadReturnSuccess, kTraceLoadReturnFail, + kTraceLoadReturnFileNotSupported, kTraceLoadReturnAlreadyOpened, kTraceLoadReturnOutOfVirtualGPUMemory, }; @@ -111,6 +112,9 @@ namespace rmv /// and is ready to show in the UI. void TraceOpened(); + /// @brief Signal to indicate that a trace file failed to open due to an error. + void TraceOpenFailed(); + /// @brief Signal to indicate that a trace file has been closed and should be /// disabled in the UI. void TraceClosed(); diff --git a/source/frontend/models/aliased_resource_model.cpp b/source/frontend/models/aliased_resource_model.cpp index b6da00a..23c6111 100644 --- a/source/frontend/models/aliased_resource_model.cpp +++ b/source/frontend/models/aliased_resource_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the aliased resource model. diff --git a/source/frontend/models/aliased_resource_model.h b/source/frontend/models/aliased_resource_model.h index 6543692..2088d64 100644 --- a/source/frontend/models/aliased_resource_model.h +++ b/source/frontend/models/aliased_resource_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the aliased resource model. diff --git a/source/frontend/models/allocation_bar_model.cpp b/source/frontend/models/allocation_bar_model.cpp index 2c30d38..0be2ccd 100644 --- a/source/frontend/models/allocation_bar_model.cpp +++ b/source/frontend/models/allocation_bar_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the allocation bar model base class. @@ -18,6 +18,7 @@ #include "rmt_types.h" #include "rmt_data_snapshot.h" +#include "util/rmv_util.h" #include "util/string_util.h" #include "managers/trace_manager.h" @@ -51,7 +52,7 @@ namespace rmv QString AllocationBarModel::GetTitleText(const RmtVirtualAllocation* allocation) const { - return "Allocation: " + QString::number(allocation->base_address) + + return "Allocation: " + rmv_util::GetVirtualAllocationName(allocation) + " - Heap: " + QString(RmtGetHeapTypeNameFromHeapType(allocation->heap_preferences[0])); } diff --git a/source/frontend/models/allocation_bar_model.h b/source/frontend/models/allocation_bar_model.h index f0faa47..27c804d 100644 --- a/source/frontend/models/allocation_bar_model.h +++ b/source/frontend/models/allocation_bar_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the allocation bar model base class. diff --git a/source/frontend/models/allocation_item_model.cpp b/source/frontend/models/allocation_item_model.cpp index cd45d3b..074b611 100644 --- a/source/frontend/models/allocation_item_model.cpp +++ b/source/frontend/models/allocation_item_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for an allocation item model. @@ -16,6 +16,7 @@ #include "managers/trace_manager.h" #include "models/snapshot/allocation_explorer_model.h" +#include "util/rmv_util.h" #include "util/string_util.h" namespace rmv @@ -90,7 +91,7 @@ namespace rmv switch (index.column()) { case kVirtualAllocationColumnId: - return QString::number(cache.virtual_allocation->base_address); + return rmv_util::GetVirtualAllocationName(cache.virtual_allocation); case kVirtualAllocationColumnAllocationSize: return rmv::string_util::LocalizedValueMemory(cache.allocation_size, false, false); case kVirtualAllocationColumnBound: diff --git a/source/frontend/models/allocation_item_model.h b/source/frontend/models/allocation_item_model.h index 346ba30..201c179 100644 --- a/source/frontend/models/allocation_item_model.h +++ b/source/frontend/models/allocation_item_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for an allocation item model. diff --git a/source/frontend/models/allocation_multi_bar_model.cpp b/source/frontend/models/allocation_multi_bar_model.cpp index a7b6802..fa258ec 100644 --- a/source/frontend/models/allocation_multi_bar_model.cpp +++ b/source/frontend/models/allocation_multi_bar_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the allocation multi bar model class. @@ -19,6 +19,7 @@ #include "managers/trace_manager.h" #include "models/snapshot/allocation_overview_model.h" +#include "util/rmv_util.h" #include "util/string_util.h" namespace rmv @@ -55,50 +56,62 @@ namespace rmv /// @param [in] virtual_allocation_b Pointer to second RmtVirtualAllocation to compare. bool operator()(const RmtVirtualAllocation* virtual_allocation_a, const RmtVirtualAllocation* virtual_allocation_b) const { - uint64_t value_a = 0; - uint64_t value_b = 0; - - // Decide which sort mode to use and calculate the comparison arguments. - switch (sort_mode_) + if (sort_mode_ == AllocationOverviewModel::kSortModeAllocationID) { - case AllocationOverviewModel::kSortModeAllocationID: - value_a = virtual_allocation_a->guid; - value_b = virtual_allocation_b->guid; - break; - - case AllocationOverviewModel::kSortModeAllocationSize: - value_a = RmtVirtualAllocationGetSizeInBytes(virtual_allocation_a); - value_b = RmtVirtualAllocationGetSizeInBytes(virtual_allocation_b); - break; - - case AllocationOverviewModel::kSortModeAllocationAge: - value_a = virtual_allocation_a->timestamp; - value_b = virtual_allocation_b->timestamp; - break; - - case AllocationOverviewModel::kSortModeResourceCount: - value_a = virtual_allocation_a->resource_count; - value_b = virtual_allocation_b->resource_count; - break; - - case AllocationOverviewModel::kSortModeFragmentationScore: - value_a = RmtVirtualAllocationGetFragmentationQuotient(virtual_allocation_a); - value_b = RmtVirtualAllocationGetFragmentationQuotient(virtual_allocation_b); - break; - - default: - // Should not get here. - RMT_ASSERT_MESSAGE(false, "Allocation overview pane: Invalid sort mode."); - break; - } + const QString value_a = rmv_util::GetVirtualAllocationName(virtual_allocation_a); + const QString value_b = rmv_util::GetVirtualAllocationName(virtual_allocation_b); - // Decide on whether ascending or descending sort is required and return the appropriate result. - if (ascending_) - { - return value_a < value_b; + + // Decide on whether ascending or descending sort is required and return the appropriate result. + if (ascending_) + { + return value_a.compare(value_b, Qt::CaseInsensitive) < 0; + } + + return value_a.compare(value_b, Qt::CaseInsensitive) > 0; } + else + { + uint64_t value_a = 0; + uint64_t value_b = 0; + + // Decide which sort mode to use and calculate the comparison arguments. + switch (sort_mode_) + { + case AllocationOverviewModel::kSortModeAllocationSize: + value_a = RmtVirtualAllocationGetSizeInBytes(virtual_allocation_a); + value_b = RmtVirtualAllocationGetSizeInBytes(virtual_allocation_b); + break; + + case AllocationOverviewModel::kSortModeAllocationAge: + value_a = virtual_allocation_a->timestamp; + value_b = virtual_allocation_b->timestamp; + break; - return value_a > value_b; + case AllocationOverviewModel::kSortModeResourceCount: + value_a = virtual_allocation_a->resource_count; + value_b = virtual_allocation_b->resource_count; + break; + + case AllocationOverviewModel::kSortModeFragmentationScore: + value_a = RmtVirtualAllocationGetFragmentationQuotient(virtual_allocation_a); + value_b = RmtVirtualAllocationGetFragmentationQuotient(virtual_allocation_b); + break; + + default: + // Should not get here. + RMT_ASSERT_MESSAGE(false, "Allocation overview pane: Invalid sort mode."); + break; + } + + // Decide on whether ascending or descending sort is required and return the appropriate result. + if (ascending_) + { + return value_a < value_b; + } + + return value_a > value_b; + } } private: diff --git a/source/frontend/models/allocation_multi_bar_model.h b/source/frontend/models/allocation_multi_bar_model.h index c9e210e..e2569de 100644 --- a/source/frontend/models/allocation_multi_bar_model.h +++ b/source/frontend/models/allocation_multi_bar_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the allocation multi bar model class. diff --git a/source/frontend/models/carousel_model.cpp b/source/frontend/models/carousel_model.cpp index 210d547..e7ccba1 100644 --- a/source/frontend/models/carousel_model.cpp +++ b/source/frontend/models/carousel_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the carousel model. diff --git a/source/frontend/models/carousel_model.h b/source/frontend/models/carousel_model.h index fa69539..7cbd8f5 100644 --- a/source/frontend/models/carousel_model.h +++ b/source/frontend/models/carousel_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the carousel model. diff --git a/source/frontend/models/colorizer.cpp b/source/frontend/models/colorizer.cpp index 63b38ae..a12724b 100644 --- a/source/frontend/models/colorizer.cpp +++ b/source/frontend/models/colorizer.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a colorizer control. diff --git a/source/frontend/models/colorizer.h b/source/frontend/models/colorizer.h index f5a0d79..55b1323 100644 --- a/source/frontend/models/colorizer.h +++ b/source/frontend/models/colorizer.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header file for a colorizer control. diff --git a/source/frontend/models/colorizer_base.cpp b/source/frontend/models/colorizer_base.cpp index 3af48df..0538fa4 100644 --- a/source/frontend/models/colorizer_base.cpp +++ b/source/frontend/models/colorizer_base.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the colorizer base class. @@ -115,18 +115,9 @@ namespace rmv case kRmtResourceUsageTypeTexture: out = rmv::RMVSettings::Get().GetColorResourceTexture(); break; - case kRmtResourceUsageTypeVertexBuffer: - out = rmv::RMVSettings::Get().GetColorResourceVertexBuffer(); - break; - case kRmtResourceUsageTypeIndexBuffer: - out = rmv::RMVSettings::Get().GetColorResourceIndexBuffer(); - break; case kRmtResourceUsageTypeRayTracingBuffer: out = rmv::RMVSettings::Get().GetColorResourceRayTracingBuffer(); break; - case kRmtResourceUsageTypeUav: - out = rmv::RMVSettings::Get().GetColorResourceUAV(); - break; case kRmtResourceUsageTypeShaderPipeline: out = rmv::RMVSettings::Get().GetColorResourceShaderPipeline(); break; @@ -351,9 +342,9 @@ namespace rmv { case kColorModePreferredHeap: case kColorModeActualHeap: + legends_scene->AddColorLegendItem(rmv::RMVSettings::Get().GetColorHeapSystem(), RmtGetHeapTypeNameFromHeapType(kRmtHeapTypeSystem)); legends_scene->AddColorLegendItem(rmv::RMVSettings::Get().GetColorHeapLocal(), RmtGetHeapTypeNameFromHeapType(kRmtHeapTypeLocal)); legends_scene->AddColorLegendItem(rmv::RMVSettings::Get().GetColorHeapInvisible(), RmtGetHeapTypeNameFromHeapType(kRmtHeapTypeInvisible)); - legends_scene->AddColorLegendItem(rmv::RMVSettings::Get().GetColorHeapSystem(), RmtGetHeapTypeNameFromHeapType(kRmtHeapTypeSystem)); legends_scene->AddColorLegendItem(rmv::RMVSettings::Get().GetColorHeapUnspecified(), RmtGetHeapTypeNameFromHeapType(kRmtHeapTypeNone)); break; diff --git a/source/frontend/models/colorizer_base.h b/source/frontend/models/colorizer_base.h index 6479081..fbf19d2 100644 --- a/source/frontend/models/colorizer_base.h +++ b/source/frontend/models/colorizer_base.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header file for the colorizer base class. @@ -77,7 +77,7 @@ namespace rmv QColor GetColor(const uint32_t color_index); /// @brief Update color legends to the UI depending on the coloring mode. - void UpdateLegends(); + virtual void UpdateLegends(); /// @brief Get the resource usage color. /// diff --git a/source/frontend/models/combo_box_model.cpp b/source/frontend/models/combo_box_model.cpp index 3d9ca6e..3f59f09 100644 --- a/source/frontend/models/combo_box_model.cpp +++ b/source/frontend/models/combo_box_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a model corresponding to a combo box. diff --git a/source/frontend/models/combo_box_model.h b/source/frontend/models/combo_box_model.h index 8ac3a1c..44da790 100644 --- a/source/frontend/models/combo_box_model.h +++ b/source/frontend/models/combo_box_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a model corresponding to a combo box. diff --git a/source/frontend/models/compare/memory_leak_finder_model.cpp b/source/frontend/models/compare/memory_leak_finder_model.cpp index 6bb31e2..11ab6a2 100644 --- a/source/frontend/models/compare/memory_leak_finder_model.cpp +++ b/source/frontend/models/compare/memory_leak_finder_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the Memory Leak Finder model. @@ -32,10 +32,12 @@ namespace rmv : ModelViewMapper(kMemoryLeakFinderNumWidgets) , table_model_(nullptr) , proxy_model_(nullptr) - , resource_thresholds_{} , stats_in_both_{} , stats_in_base_only_{} , stats_in_diff_only_{} + , base_index_(kSnapshotCompareBase) + , diff_index_(kSnapshotCompareDiff) + { ResetStats(); } @@ -63,8 +65,6 @@ namespace rmv table_model_->removeRows(0, table_model_->rowCount()); table_model_->SetRowCount(0); - memset(resource_thresholds_, 0, sizeof(uint64_t) * (kSizeSliderRange + 1)); - SetModelData(kMemoryLeakFinderBaseStats, "-"); SetModelData(kMemoryLeakFinderBothStats, "-"); SetModelData(kMemoryLeakFinderDiffStats, "-"); @@ -76,20 +76,20 @@ namespace rmv SetModelData(kMemoryLeakFinderDiffSnapshot, "-"); } - void MemoryLeakFinderModel::Update(SnapshotCompareId compare_filter) + bool MemoryLeakFinderModel::Update(SnapshotCompareId compare_filter) { if (!TraceManager::Get().DataSetValid()) { - return; + return false; } const SnapshotManager& snapshot_manager = SnapshotManager::Get(); - const RmtDataSnapshot* base_snapshot = snapshot_manager.GetCompareSnapshot(kSnapshotCompareBase); - const RmtDataSnapshot* diff_snapshot = snapshot_manager.GetCompareSnapshot(kSnapshotCompareDiff); + const RmtDataSnapshot* base_snapshot = snapshot_manager.GetCompareSnapshot(base_index_); + const RmtDataSnapshot* diff_snapshot = snapshot_manager.GetCompareSnapshot(diff_index_); if (base_snapshot == nullptr || diff_snapshot == nullptr) { - return; + return false; } RmtSnapshotPoint* base_snapshot_point = base_snapshot->snapshot_point; @@ -97,7 +97,7 @@ namespace rmv if (base_snapshot_point == nullptr || diff_snapshot_point == nullptr) { - return; + return false; } const QString base_snapshot_name = QString(base_snapshot_point->name); @@ -182,9 +182,18 @@ namespace rmv proxy_model_->UpdateCompareFilter(compare_filter); proxy_model_->invalidate(); - UpdateResourceThresholds(); - UpdateLabels(); + + return true; + } + + bool MemoryLeakFinderModel::SwapSnapshots(SnapshotCompareId compare_filter) + { + CompareSnapshots temp = diff_index_; + diff_index_ = base_index_; + base_index_ = temp; + + return Update(compare_filter); } void MemoryLeakFinderModel::ResetStats() @@ -197,26 +206,6 @@ namespace rmv stats_in_diff_only_.size = 0; } - void MemoryLeakFinderModel::UpdateResourceThresholds() - { - uint32_t row_count = table_model_->rowCount(); - if (row_count > 0) - { - std::vector resource_sizes; - resource_sizes.reserve(row_count); - - for (uint32_t loop = 0; loop < row_count; loop++) - { - QModelIndex model_index = table_model_->index(loop, kResourceColumnSize, QModelIndex()); - if (model_index.isValid() == true) - { - resource_sizes.push_back(table_model_->data(model_index, Qt::UserRole).toULongLong()); - } - } - rmv_util::BuildResourceSizeThresholds(resource_sizes, resource_thresholds_); - } - } - void MemoryLeakFinderModel::UpdateLabels() { SetModelData(kMemoryLeakFinderBaseStats, @@ -252,8 +241,8 @@ namespace rmv void MemoryLeakFinderModel::FilterBySizeChanged(int min_value, int max_value) { - const uint64_t scaled_min = resource_thresholds_[min_value]; - const uint64_t scaled_max = resource_thresholds_[max_value]; + const uint64_t scaled_min = rmv_util::CalculateSizeThresholdFromStepValue(min_value, rmv::kSizeSliderRange - 1); + const uint64_t scaled_max = rmv_util::CalculateSizeThresholdFromStepValue(max_value, rmv::kSizeSliderRange - 1); proxy_model_->SetSizeFilter(scaled_min, scaled_max); proxy_model_->invalidate(); @@ -287,11 +276,11 @@ namespace rmv // Use base snapshot if open or common to both. if ((compare_id & kSnapshotCompareIdOpen) != 0 || (compare_id & kSnapshotCompareIdCommon) != 0) { - snapshot = snapshot_manager.GetCompareSnapshot(kSnapshotCompareBase); + snapshot = snapshot_manager.GetCompareSnapshot(base_index_); } else { - snapshot = snapshot_manager.GetCompareSnapshot(kSnapshotCompareDiff); + snapshot = snapshot_manager.GetCompareSnapshot(diff_index_); } // Set up the single snapshot point for loading (if necessary). diff --git a/source/frontend/models/compare/memory_leak_finder_model.h b/source/frontend/models/compare/memory_leak_finder_model.h index 58bfbc1..bcfa3dd 100644 --- a/source/frontend/models/compare/memory_leak_finder_model.h +++ b/source/frontend/models/compare/memory_leak_finder_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Memory Leak Finder model. @@ -15,6 +15,7 @@ #include "rmt_resource_list.h" #include "rmt_virtual_allocation_list.h" +#include "managers/snapshot_manager.h" #include "models/proxy_models/memory_leak_finder_proxy_model.h" #include "models/resource_item_model.h" #include "util/constants.h" @@ -58,7 +59,16 @@ namespace rmv /// @brief Update the model. /// /// @param [in] compare_filter The compare filter ID, to indicate which resources are to be displayed. - void Update(SnapshotCompareId compare_filter); + /// + /// @return true if the model was updated successfully, false otherwise. + bool Update(SnapshotCompareId compare_filter); + + /// @brief Swap the snapshots. + /// + /// @param [in] compare_filter The compare filter ID, to indicate which resources are to be displayed. + /// + /// @return true if the snapshots were swapped successfully, false otherwise. + bool SwapSnapshots(SnapshotCompareId compare_filter); /// @brief Initialize blank data for the model. void ResetModelValues(); @@ -101,20 +111,14 @@ namespace rmv RmtSnapshotPoint* FindSnapshot(const QModelIndex& index) const; private: - /// @brief Update the resource size buckets. - /// - /// This is used by the double-slider to group the resource sizes. Called whenever the table data changes. - void UpdateResourceThresholds(); - /// @brief Update labels at the bottom. void UpdateLabels(); /// @brief Reset the snapshot stats. void ResetStats(); - ResourceItemModel* table_model_; ///< The data for the resource table. - MemoryLeakFinderProxyModel* proxy_model_; ///< The proxy model for the resource table. - uint64_t resource_thresholds_[kSizeSliderRange + 1]; ///< List of resource size thresholds for the filter by size sliders. + ResourceItemModel* table_model_; ///< The data for the resource table. + MemoryLeakFinderProxyModel* proxy_model_; ///< The proxy model for the resource table. /// @brief struct to describe the snapshot statistics struct SnapshotStats @@ -126,6 +130,9 @@ namespace rmv SnapshotStats stats_in_both_; ///< Attributes in both snapshots. SnapshotStats stats_in_base_only_; ///< Attributes in the base snapshot only. SnapshotStats stats_in_diff_only_; ///< Attributes in the diff snapshot only. + + CompareSnapshots base_index_; ///< The index of the base snapshot. + CompareSnapshots diff_index_; ///< The index of the diff snapshot. }; } // namespace rmv diff --git a/source/frontend/models/compare/snapshot_delta_model.cpp b/source/frontend/models/compare/snapshot_delta_model.cpp index f169bd6..ab62cad 100644 --- a/source/frontend/models/compare/snapshot_delta_model.cpp +++ b/source/frontend/models/compare/snapshot_delta_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the Snapshot Delta model. diff --git a/source/frontend/models/compare/snapshot_delta_model.h b/source/frontend/models/compare/snapshot_delta_model.h index eda85b9..2c6999f 100644 --- a/source/frontend/models/compare/snapshot_delta_model.h +++ b/source/frontend/models/compare/snapshot_delta_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Snapshot Delta model. diff --git a/source/frontend/models/heap_combo_box_model.cpp b/source/frontend/models/heap_combo_box_model.cpp index 2f01b3c..6276af1 100644 --- a/source/frontend/models/heap_combo_box_model.cpp +++ b/source/frontend/models/heap_combo_box_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a model corresponding to a heap combo box. diff --git a/source/frontend/models/heap_combo_box_model.h b/source/frontend/models/heap_combo_box_model.h index 1283392..9753a0d 100644 --- a/source/frontend/models/heap_combo_box_model.h +++ b/source/frontend/models/heap_combo_box_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a model corresponding to a heap combo box. diff --git a/source/frontend/models/proxy_models/allocation_proxy_model.cpp b/source/frontend/models/proxy_models/allocation_proxy_model.cpp index 36bf4cc..f12522c 100644 --- a/source/frontend/models/proxy_models/allocation_proxy_model.cpp +++ b/source/frontend/models/proxy_models/allocation_proxy_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a proxy filter that processes multiple columns @@ -67,12 +67,9 @@ namespace rmv bool AllocationProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { - if ((left.column() == kVirtualAllocationColumnId && right.column() == kVirtualAllocationColumnId)) + if ((left.column() == kVirtualAllocationColumnId) && (right.column() == kVirtualAllocationColumnId)) { - const qulonglong addr_left = left.data().toULongLong(); - const qulonglong addr_right = right.data().toULongLong(); - - return addr_left < addr_right; + return left.data().toString().compare(right.data().toString(), Qt::CaseInsensitive) < 0; } else if ((left.column() == kVirtualAllocationColumnAllocationSize && right.column() == kVirtualAllocationColumnAllocationSize)) { diff --git a/source/frontend/models/proxy_models/allocation_proxy_model.h b/source/frontend/models/proxy_models/allocation_proxy_model.h index 7640113..9a8bb1d 100644 --- a/source/frontend/models/proxy_models/allocation_proxy_model.h +++ b/source/frontend/models/proxy_models/allocation_proxy_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a proxy filter that processes multiple columns diff --git a/source/frontend/models/proxy_models/memory_leak_finder_proxy_model.cpp b/source/frontend/models/proxy_models/memory_leak_finder_proxy_model.cpp index 2a328b0..fd0de07 100644 --- a/source/frontend/models/proxy_models/memory_leak_finder_proxy_model.cpp +++ b/source/frontend/models/proxy_models/memory_leak_finder_proxy_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a proxy filter that processes multiple columns. diff --git a/source/frontend/models/proxy_models/memory_leak_finder_proxy_model.h b/source/frontend/models/proxy_models/memory_leak_finder_proxy_model.h index 78be596..de99d5b 100644 --- a/source/frontend/models/proxy_models/memory_leak_finder_proxy_model.h +++ b/source/frontend/models/proxy_models/memory_leak_finder_proxy_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a proxy filter that processes multiple columns of the diff --git a/source/frontend/models/proxy_models/resource_details_proxy_model.cpp b/source/frontend/models/proxy_models/resource_details_proxy_model.cpp index 10879e9..51ccc6e 100644 --- a/source/frontend/models/proxy_models/resource_details_proxy_model.cpp +++ b/source/frontend/models/proxy_models/resource_details_proxy_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a proxy filter that processes the resource details diff --git a/source/frontend/models/proxy_models/resource_details_proxy_model.h b/source/frontend/models/proxy_models/resource_details_proxy_model.h index c2bcd86..596db57 100644 --- a/source/frontend/models/proxy_models/resource_details_proxy_model.h +++ b/source/frontend/models/proxy_models/resource_details_proxy_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a proxy filter that processes the resource details table diff --git a/source/frontend/models/proxy_models/resource_proxy_model.cpp b/source/frontend/models/proxy_models/resource_proxy_model.cpp index 443c314..95cc6ac 100644 --- a/source/frontend/models/proxy_models/resource_proxy_model.cpp +++ b/source/frontend/models/proxy_models/resource_proxy_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a proxy filter that processes multiple columns. @@ -53,7 +53,7 @@ namespace rmv void ResourceProxyModel::SetResourceUsageFilter(const QString& resource_usage_filter) { - resource_usage_filter_ = QRegularExpression(resource_usage_filter, QRegularExpression::CaseInsensitiveOption); + resource_usage_filter_ = QRegularExpression(QRegularExpression::anchoredPattern(resource_usage_filter), QRegularExpression::CaseInsensitiveOption); } bool ResourceProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const @@ -130,50 +130,87 @@ namespace rmv return true; } + bool ResourceProxyModel::SortIdentical(const QModelIndex& left, const QModelIndex& right) const + { + // Left and right are identical, so sort by heap first, then resources. + const QModelIndex left_index = sourceModel()->index(left.row(), kResourceColumnUsage, QModelIndex()); + const QModelIndex right_index = sourceModel()->index(right.row(), kResourceColumnUsage, QModelIndex()); + + const int left_resource = left_index.data(Qt::UserRole).toInt(); + const int right_resource = right_index.data(Qt::UserRole).toInt(); + if (left_resource == kRmtResourceUsageTypeHeap) + { + return true; + } + else if (right_resource == kRmtResourceUsageTypeHeap) + { + return false; + } + return QSortFilterProxyModel::lessThan(left, right); + } + bool ResourceProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { if ((left.column() == kResourceColumnVirtualAddress && right.column() == kResourceColumnVirtualAddress)) { const qulonglong left_data = left.data(Qt::UserRole).toULongLong(); const qulonglong right_data = right.data(Qt::UserRole).toULongLong(); - + if (left_data == right_data) + { + return SortIdentical(left, right); + } return left_data < right_data; } else if ((left.column() == kResourceColumnSize && right.column() == kResourceColumnSize)) { const qulonglong left_data = left.data(Qt::UserRole).toULongLong(); const qulonglong right_data = right.data(Qt::UserRole).toULongLong(); - + if (left_data == right_data) + { + return SortIdentical(left, right); + } return left_data < right_data; } else if ((left.column() == kResourceColumnMappedInvisible && right.column() == kResourceColumnMappedInvisible)) { const double left_data = left.data(Qt::UserRole).toDouble(); const double right_data = right.data(Qt::UserRole).toDouble(); - + if (left_data == right_data) + { + return SortIdentical(left, right); + } return left_data < right_data; } else if ((left.column() == kResourceColumnMappedLocal && right.column() == kResourceColumnMappedLocal)) { const double left_data = left.data(Qt::UserRole).toDouble(); const double right_data = right.data(Qt::UserRole).toDouble(); - + if (left_data == right_data) + { + return SortIdentical(left, right); + } return left_data < right_data; } else if ((left.column() == kResourceColumnMappedHost && right.column() == kResourceColumnMappedHost)) { const double left_data = left.data(Qt::UserRole).toDouble(); const double right_data = right.data(Qt::UserRole).toDouble(); - + if (left_data == right_data) + { + return SortIdentical(left, right); + } return left_data < right_data; } else if ((left.column() == kResourceColumnMappedNone && right.column() == kResourceColumnMappedNone)) { const double left_data = left.data(Qt::UserRole).toDouble(); const double right_data = right.data(Qt::UserRole).toDouble(); - + if (left_data == right_data) + { + return SortIdentical(left, right); + } return left_data < right_data; } return QSortFilterProxyModel::lessThan(left, right); } -} // namespace rmv \ No newline at end of file +} // namespace rmv diff --git a/source/frontend/models/proxy_models/resource_proxy_model.h b/source/frontend/models/proxy_models/resource_proxy_model.h index b610376..758f9c2 100644 --- a/source/frontend/models/proxy_models/resource_proxy_model.h +++ b/source/frontend/models/proxy_models/resource_proxy_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a proxy filter that processes multiple columns @@ -75,6 +75,16 @@ namespace rmv virtual bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; private: + /// @brief Handle sorting when two resource parameters are identical. + /// + /// In this case, the heap resource is listed first. + /// + /// @param [in] left The left item to compare. + /// @param [in] right The right item to compare. + /// + /// @return true if left is less than right, false otherwise. + bool SortIdentical(const QModelIndex& left, const QModelIndex& right) const; + QRegularExpression preferred_heap_filter_; ///< The preferred heap filter regular expression. QRegularExpression resource_usage_filter_; ///< The resource usage filter regular expression. }; diff --git a/source/frontend/models/proxy_models/snapshot_timeline_proxy_model.cpp b/source/frontend/models/proxy_models/snapshot_timeline_proxy_model.cpp index 37d33d3..5136866 100644 --- a/source/frontend/models/proxy_models/snapshot_timeline_proxy_model.cpp +++ b/source/frontend/models/proxy_models/snapshot_timeline_proxy_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a proxy filter that processes multiple columns. diff --git a/source/frontend/models/proxy_models/snapshot_timeline_proxy_model.h b/source/frontend/models/proxy_models/snapshot_timeline_proxy_model.h index c5417d5..31fc7ee 100644 --- a/source/frontend/models/proxy_models/snapshot_timeline_proxy_model.h +++ b/source/frontend/models/proxy_models/snapshot_timeline_proxy_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a proxy filter that processes multiple columns of the diff --git a/source/frontend/models/proxy_models/table_proxy_model.cpp b/source/frontend/models/proxy_models/table_proxy_model.cpp index 54a7293..5c1b41e 100644 --- a/source/frontend/models/proxy_models/table_proxy_model.cpp +++ b/source/frontend/models/proxy_models/table_proxy_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a proxy filter that processes multiple columns. diff --git a/source/frontend/models/proxy_models/table_proxy_model.h b/source/frontend/models/proxy_models/table_proxy_model.h index b147492..ac02c01 100644 --- a/source/frontend/models/proxy_models/table_proxy_model.h +++ b/source/frontend/models/proxy_models/table_proxy_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a proxy filter that processes multiple columns. diff --git a/source/frontend/models/resource_item_model.cpp b/source/frontend/models/resource_item_model.cpp index eaa0cfd..49ac1b2 100644 --- a/source/frontend/models/resource_item_model.cpp +++ b/source/frontend/models/resource_item_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a resource item model. @@ -17,6 +17,7 @@ #include "rmt_util.h" #include "managers/trace_manager.h" +#include "util/rmv_util.h" #include "util/string_util.h" namespace rmv @@ -154,7 +155,7 @@ namespace rmv { if (resource->bound_allocation != nullptr) { - return QString::number(resource->bound_allocation->guid); + return rmv_util::GetVirtualAllocationName(resource->bound_allocation); } else { @@ -188,6 +189,11 @@ namespace rmv return QVariant::fromValue(cache_[row].host_bytes); case kResourceColumnMappedNone: return QVariant::fromValue(cache_[row].unmapped_bytes); + case kResourceColumnUsage: + { + const RmtResourceUsageType resource_usage_type = RmtResourceGetUsageType(resource); + return QVariant::fromValue(resource_usage_type); + } case kResourceColumnGlobalId: return QVariant::fromValue(resource->identifier); diff --git a/source/frontend/models/resource_item_model.h b/source/frontend/models/resource_item_model.h index d19aa69..b5a78c9 100644 --- a/source/frontend/models/resource_item_model.h +++ b/source/frontend/models/resource_item_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a resource item model. diff --git a/source/frontend/models/resource_sorter.cpp b/source/frontend/models/resource_sorter.cpp index 6bbb190..02ef754 100644 --- a/source/frontend/models/resource_sorter.cpp +++ b/source/frontend/models/resource_sorter.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a resource sorter. diff --git a/source/frontend/models/resource_sorter.h b/source/frontend/models/resource_sorter.h index d353c34..e57e62d 100644 --- a/source/frontend/models/resource_sorter.h +++ b/source/frontend/models/resource_sorter.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a resource sorter. diff --git a/source/frontend/models/resource_usage_combo_box_model.cpp b/source/frontend/models/resource_usage_combo_box_model.cpp index bc15008..8a2c076 100644 --- a/source/frontend/models/resource_usage_combo_box_model.cpp +++ b/source/frontend/models/resource_usage_combo_box_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a model corresponding to a resource combo box. @@ -19,16 +19,26 @@ #include -// Set of resources that shouldn't be in the resource combo box. -static const std::set kExcludedResources = {kRmtResourceUsageTypeUnknown}; +// Set of resources that shouldn't be in the resource combo box or are specially managed. +static const std::set kExcludedResources = {RmtResourceUsageType::kRmtResourceUsageTypeUnknown, + RmtResourceUsageType::kRmtResourceUsageTypeHeap, + RmtResourceUsageType::kRmtResourceUsageTypeAll}; // Set of resources that should be disabled in the resource combo box. static const std::set kDisabledResources = {kRmtResourceUsageTypeHeap, kRmtResourceUsageTypeFree}; +// Indentation string for checkbox labels. +static const QString kCheckboxIndentationString("> "); + +// Indicates an invalid index for the combobox. +static const int kInvalidIndex = -1; + namespace rmv { ResourceUsageComboBoxModel::ResourceUsageComboBoxModel() : ComboBoxModel() + , heap_checkbox_item_index_(kInvalidIndex) + , all_checkbox_item_index_(kInvalidIndex) { // Inform the model which entries are ignored in the UI. SetupExcludeIndexList(kExcludedResources); @@ -40,25 +50,40 @@ namespace rmv void ResourceUsageComboBoxModel::SetupResourceComboBox(ArrowIconComboBox* combo_box) { - // Add the "All" entry to the combo box. - QCheckBox* checkbox = combo_box->AddCheckboxItem("All", QVariant(), false, true); + // Add the "Heap" checkbox to the combo box. + heap_checkbox_item_index_ = combo_box->RowCount(); + QCheckBox* checkbox = combo_box->AddCheckboxItem(RmtGetResourceUsageTypeNameFromResourceUsageType(RmtResourceUsageType::kRmtResourceUsageTypeHeap), + RmtResourceUsageType::kRmtResourceUsageTypeHeap, + false, + false); RMT_ASSERT(checkbox != nullptr); if (checkbox != nullptr) { - connect(checkbox, &QCheckBox::clicked, this, [=]() { emit FilterChanged(true); }); + connect(checkbox, &QCheckBox::clicked, this, [=]() { emit FilterChanged(true, heap_checkbox_item_index_); }); + } + + // Add the "All" checkbox to the combo box. + all_checkbox_item_index_ = combo_box->RowCount(); + checkbox = combo_box->AddCheckboxItem("All resource usage types", RmtResourceUsageType::kRmtResourceUsageTypeCount, false, false); + RMT_ASSERT(checkbox != nullptr); + if (checkbox != nullptr) + { + connect(checkbox, &QCheckBox::clicked, this, [=]() { emit FilterChanged(true, all_checkbox_item_index_); }); } // Add resources if they are not excluded. - for (int i = 0; i < static_cast(kRmtResourceUsageTypeCount); i++) + for (int i = 0; i < static_cast(RmtResourceUsageType::kRmtResourceUsageTypeCount); i++) { - auto it = kExcludedResources.find(i); + const auto it = kExcludedResources.find(i); if (it == kExcludedResources.end()) { - checkbox = combo_box->AddCheckboxItem(RmtGetResourceUsageTypeNameFromResourceUsageType(RmtResourceUsageType(i)), QVariant(), false, false); + checkbox = combo_box->AddCheckboxItem( + kCheckboxIndentationString + RmtGetResourceUsageTypeNameFromResourceUsageType(RmtResourceUsageType(i)), i, false, false); RMT_ASSERT(checkbox != nullptr); if (checkbox != nullptr) { - connect(checkbox, &QCheckBox::clicked, this, [=]() { emit FilterChanged(true); }); + const int item_index = combo_box->RowCount() - 1; + connect(checkbox, &QCheckBox::clicked, this, [=]() { emit FilterChanged(true, item_index); }); } } } @@ -67,34 +92,35 @@ namespace rmv void ResourceUsageComboBoxModel::ResetResourceComboBox(ArrowIconComboBox* combo_box) { - // Index 0 is the "all" combo box entry. + combo_box->SetChecked(heap_checkbox_item_index_, false); + if (kDisabledResources.size() > 0) { - // If there are disabled resources, then disable the "All" checkbox. - int combo_box_row = 0; - combo_box->SetChecked(combo_box_row, false); - combo_box_row++; - - for (int i = 0; i < static_cast(kRmtResourceUsageTypeCount); i++) + const int item_count = combo_box->RowCount(); + for (int i = 0; i < item_count; i++) { - // If this resource is excluded, skip it. - auto exclude_it = kExcludedResources.find(i); - if (exclude_it != kExcludedResources.end()) - { - continue; - } + const RmtResourceUsageType usage_type = static_cast(combo_box->ItemData(i).toInt()); - auto disabled_it = kDisabledResources.find(i); + const auto disabled_it = kDisabledResources.find(usage_type); if (disabled_it != kDisabledResources.end()) { - combo_box->SetChecked(combo_box_row, false); + combo_box->SetChecked(i, false); } else { - combo_box->SetChecked(combo_box_row, true); + combo_box->SetChecked(i, true); + } + + // If this resource is excluded, skip it. + const auto exclude_it = kExcludedResources.find(usage_type); + if (exclude_it != kExcludedResources.end()) + { + continue; } - combo_box_row++; } + + // Since there are some unchecked usage types, the "All" checkbox needs to be uncheck. + combo_box->SetChecked(all_checkbox_item_index_, false); } SetupState(combo_box); } @@ -105,12 +131,10 @@ namespace rmv // Build the resource filter. QString resource_filter = QString("(="); - for (int resource = 0; resource < kRmtResourceUsageTypeCount; resource++) + + for (auto item_usage_type : checked_resource_usage_types_) { - if (ItemInList(resource) == true) - { - resource_filter += "|" + QString(RmtGetResourceUsageTypeNameFromResourceUsageType(static_cast(resource))); - } + resource_filter += "|" + QString(RmtGetResourceUsageTypeNameFromResourceUsageType(item_usage_type)); } resource_filter += ")"; @@ -125,9 +149,16 @@ namespace rmv uint64_t filter_mask = 0; - for (int usage_type = kRmtResourceUsageTypeFree; usage_type < kRmtResourceUsageTypeCount; usage_type++) + const int item_count = combo_box->RowCount(); + for (int i = 0; i < item_count; i++) { - if (ItemInList(usage_type) == true) + if (i == all_checkbox_item_index_) + { + continue; + } + + const RmtResourceUsageType usage_type = static_cast(combo_box->ItemData(i).toInt()); + if (combo_box->IsChecked(i)) { filter_mask |= static_cast(std::pow(2, usage_type - 1)); } @@ -136,9 +167,121 @@ namespace rmv return filter_mask; } + bool ResourceUsageComboBoxModel::ItemInList(int usage_type) const + { + bool result = false; + + for (auto item_usage_type : checked_resource_usage_types_) + { + if (item_usage_type == usage_type) + { + result = true; + break; + } + } + + return result; + } + void ResourceUsageComboBoxModel::SetupState(const ArrowIconComboBox* combo_box) { - ComboBoxModel::SetupState(combo_box, true); + checked_resource_usage_types_.clear(); + if (combo_box->IsChecked(heap_checkbox_item_index_)) + { + checked_resource_usage_types_.insert(RmtResourceUsageType::kRmtResourceUsageTypeHeap); + } + else + { + const int item_count = combo_box->RowCount(); + for (int i = 0; i < item_count; i++) + { + if (i == all_checkbox_item_index_) + { + continue; + } + + const RmtResourceUsageType usage_type = static_cast(combo_box->ItemData(i).toInt()); + if (combo_box->IsChecked(i)) + { + checked_resource_usage_types_.insert(usage_type); + } + } + } } + void ResourceUsageComboBoxModel::UpdateCheckboxes(const int changed_item_index, ArrowIconComboBox* combo_box) + { + const int item_count = combo_box->RowCount(); + + if (changed_item_index == all_checkbox_item_index_) + { + // Handle case where "All" checkbox changed. Uncheck Heap and either check or uncheck all other checkbox items. + const bool all_usage_types_checked = combo_box->IsChecked(changed_item_index); + + for (int index = 0; index < item_count; index++) + { + if (index == changed_item_index) + { + continue; + } + + RmtResourceUsageType item_resource_usage_type = static_cast(combo_box->ItemData(index).toInt()); + + if ((all_usage_types_checked) && (item_resource_usage_type == RmtResourceUsageType::kRmtResourceUsageTypeHeap)) + { + combo_box->SetChecked(index, false); + } + else + { + // Handle all other checkbox items. + combo_box->SetChecked(index, all_usage_types_checked); + } + } + } + else + { + // Uncheck "All" checkbox item. + combo_box->SetChecked(all_checkbox_item_index_, false); + + if (changed_item_index == heap_checkbox_item_index_) + { + if (combo_box->IsChecked(changed_item_index)) + { + // Handle case where "Heap" checked. Uncheck all other items. + for (int index = 0; index < item_count; index++) + { + if (index == heap_checkbox_item_index_) // skip heap checkbox. + { + continue; + } + + combo_box->SetChecked(index, false); + } + } + } + else + { + // A usage type checkbox was checked so uncheck the "Heap" checkbox. + combo_box->SetChecked(heap_checkbox_item_index_, false); + + // If all usage types are checked, also check the "All" checkbox. Otherwise, uncheck the "All" checkbox. + bool all_usage_types_checked = true; + for (int index = 0; index < item_count; index++) + { + if (index == heap_checkbox_item_index_) + { + continue; + } + + if (index == all_checkbox_item_index_) + { + continue; + } + + all_usage_types_checked &= combo_box->IsChecked(index); + } + combo_box->SetChecked(all_checkbox_item_index_, all_usage_types_checked); + } + } + } } // namespace rmv \ No newline at end of file diff --git a/source/frontend/models/resource_usage_combo_box_model.h b/source/frontend/models/resource_usage_combo_box_model.h index 9e40ef2..a4808a1 100644 --- a/source/frontend/models/resource_usage_combo_box_model.h +++ b/source/frontend/models/resource_usage_combo_box_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a model corresponding to a resource combo box. @@ -10,6 +10,8 @@ #include "models/combo_box_model.h" +#include "rmt_format.h" + namespace rmv { /// @brief Model encapsulating everything needed for a resource combo box. @@ -48,16 +50,35 @@ namespace rmv /// @return Resource usage bit mask. uint64_t GetFilterMask(const ArrowIconComboBox* combo_box); + /// @brief Check if an item is in the list. + /// + /// @param [in] item The item to search for. + /// + /// @return true if item is found in the list, false otherwise. + bool ItemInList(int item) const; + /// @brief Check the state of the combo box and setup the internal state representation of the ArrowIconComboBox. /// /// @param [in] combo_box Pointer to the combo box whose state is to be examined. void SetupState(const ArrowIconComboBox* combo_box); + /// @brief Update the full set of checkboxes in the combobox based on the checkbox was changed. + /// + /// @param [in] changed_item_index The index of the item in the combo box change was updated. + /// @param [in] combo_box A pointer to the combo box. + void UpdateCheckboxes(int changed_item_index, ArrowIconComboBox* combo_box); + signals: /// @brief Signal emitted when a combo box item is changed. /// - /// @param [in] checked The checked state of the filter. - void FilterChanged(bool checked); + /// @param [in] checked The checked state of the filter. + /// @param [in] item_index The index of the combo box item that changed. + void FilterChanged(bool checked, int item_index); + + private: + int heap_checkbox_item_index_; ///< The combo box item index for the "Heap" checkbox. + int all_checkbox_item_index_; ///< The combo box item index for the "All" checkbox. + std::set checked_resource_usage_types_; ///< The list of checked resource usage types. }; } // namespace rmv diff --git a/source/frontend/models/snapshot/allocation_explorer_model.cpp b/source/frontend/models/snapshot/allocation_explorer_model.cpp index f446707..4c7d616 100644 --- a/source/frontend/models/snapshot/allocation_explorer_model.cpp +++ b/source/frontend/models/snapshot/allocation_explorer_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the Allocation explorer model. @@ -28,7 +28,6 @@ namespace rmv , resource_table_model_(nullptr) , allocation_proxy_model_(nullptr) , resource_proxy_model_(nullptr) - , resource_thresholds_{} , minimum_allocation_size_(0) , maximum_allocation_size_(0) { @@ -52,7 +51,6 @@ namespace rmv resource_table_model_->SetRowCount(0); allocation_proxy_model_->invalidate(); resource_proxy_model_->invalidate(); - memset(resource_thresholds_, 0, sizeof(uint64_t) * (kSizeSliderRange + 1)); allocation_bar_model_->ClearSelectionState(); } @@ -171,9 +169,8 @@ namespace rmv void VirtualAllocationExplorerModel::AllocationSizeFilterChanged(int min_value, int max_value) const { - const uint64_t diff = maximum_allocation_size_ - minimum_allocation_size_; - const uint64_t scaled_min = ((min_value * diff) / kSizeSliderRange) + minimum_allocation_size_; - const uint64_t scaled_max = ((max_value * diff) / kSizeSliderRange) + minimum_allocation_size_; + const uint64_t scaled_min = rmv_util::CalculateSizeThresholdFromStepValue(min_value, rmv::kSizeSliderRange - 1); + const uint64_t scaled_max = rmv_util::CalculateSizeThresholdFromStepValue(max_value, rmv::kSizeSliderRange - 1); allocation_proxy_model_->SetSizeFilter(scaled_min, scaled_max); allocation_proxy_model_->invalidate(); @@ -189,8 +186,8 @@ namespace rmv { if (allocation_bar_model_->GetAllocation(0, 0) != nullptr) { - const uint64_t scaled_min = resource_thresholds_[min_value]; - const uint64_t scaled_max = resource_thresholds_[max_value]; + const uint64_t scaled_min = rmv_util::CalculateSizeThresholdFromStepValue(min_value, rmv::kSizeSliderRange - 1); + const uint64_t scaled_max = rmv_util::CalculateSizeThresholdFromStepValue(max_value, rmv::kSizeSliderRange - 1); resource_proxy_model_->SetSizeFilter(scaled_min, scaled_max); resource_proxy_model_->invalidate(); @@ -207,24 +204,6 @@ namespace rmv return resource_proxy_model_; } - void VirtualAllocationExplorerModel::BuildResourceSizeThresholds() - { - std::vector resource_sizes; - - const RmtVirtualAllocation* selected_allocation = allocation_bar_model_->GetAllocation(0, 0); - - if (selected_allocation != nullptr && selected_allocation->resource_count > 0) - { - int32_t resource_count = selected_allocation->resource_count; - resource_sizes.reserve(resource_count); - for (int current_resource_index = 0; current_resource_index < selected_allocation->resource_count; current_resource_index++) - { - resource_sizes.push_back(selected_allocation->resources[current_resource_index]->size_in_bytes); - } - rmv_util::BuildResourceSizeThresholds(resource_sizes, resource_thresholds_); - } - } - AllocationBarModel* VirtualAllocationExplorerModel::GetAllocationBarModel() const { return allocation_bar_model_; diff --git a/source/frontend/models/snapshot/allocation_explorer_model.h b/source/frontend/models/snapshot/allocation_explorer_model.h index 6dd9f03..43ef40f 100644 --- a/source/frontend/models/snapshot/allocation_explorer_model.h +++ b/source/frontend/models/snapshot/allocation_explorer_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Allocation explorer model. @@ -117,9 +117,6 @@ namespace rmv /// @return The number of resources in the allocation. int32_t UpdateResourceTable(); - /// @brief Build a list of resource size thresholds for the filter by size slider. - void BuildResourceSizeThresholds(); - /// @brief Get the allocation proxy model. /// /// Used to set up a connection between the table being sorted and the UI update. @@ -138,14 +135,13 @@ namespace rmv AllocationBarModel* GetAllocationBarModel() const; private: - AllocationBarModel* allocation_bar_model_; ///< The model for the allocation bar graph. - AllocationItemModel* allocation_table_model_; ///< Holds the allocation table data. - ResourceItemModel* resource_table_model_; ///< Holds the resource table data. - AllocationProxyModel* allocation_proxy_model_; ///< Allocation table proxy model. - ResourceProxyModel* resource_proxy_model_; ///< Resource table proxy model. - uint64_t resource_thresholds_[kSizeSliderRange + 1]; ///< List of resource size thresholds for the filter by size sliders. - uint64_t minimum_allocation_size_; ///< The size of the smallest allocation. - uint64_t maximum_allocation_size_; ///< The size of the largest allocation. + AllocationBarModel* allocation_bar_model_; ///< The model for the allocation bar graph. + AllocationItemModel* allocation_table_model_; ///< Holds the allocation table data. + ResourceItemModel* resource_table_model_; ///< Holds the resource table data. + AllocationProxyModel* allocation_proxy_model_; ///< Allocation table proxy model. + ResourceProxyModel* resource_proxy_model_; ///< Resource table proxy model. + uint64_t minimum_allocation_size_; ///< The size of the smallest allocation. + uint64_t maximum_allocation_size_; ///< The size of the largest allocation. }; } // namespace rmv diff --git a/source/frontend/models/snapshot/allocation_overview_model.cpp b/source/frontend/models/snapshot/allocation_overview_model.cpp index 196d33c..e5787d6 100644 --- a/source/frontend/models/snapshot/allocation_overview_model.cpp +++ b/source/frontend/models/snapshot/allocation_overview_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the allocation overview model. diff --git a/source/frontend/models/snapshot/allocation_overview_model.h b/source/frontend/models/snapshot/allocation_overview_model.h index 43b9657..65cb575 100644 --- a/source/frontend/models/snapshot/allocation_overview_model.h +++ b/source/frontend/models/snapshot/allocation_overview_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Allocation overview model. diff --git a/source/frontend/models/snapshot/heap_overview_heap_model.cpp b/source/frontend/models/snapshot/heap_overview_heap_model.cpp index 9c1796f..c944434 100644 --- a/source/frontend/models/snapshot/heap_overview_heap_model.cpp +++ b/source/frontend/models/snapshot/heap_overview_heap_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a model for a heap layout for the Heap Overview @@ -61,6 +61,9 @@ namespace rmv SetModelData(kHeapOverviewCpuVisible, "-"); SetModelData(kHeapOverviewGpuCached, "-"); SetModelData(kHeapOverviewGpuVisible, "-"); + SetModelData(kHeapOverviewCommitted, "-"); + SetModelData(kHeapOverviewResourceCount, "-"); + SetModelData(kHeapOverviewAllocationCount, "-"); SetModelData(kHeapOverviewSmallestAllocation, "-"); SetModelData(kHeapOverviewLargestAllocation, "-"); SetModelData(kHeapOverviewMeanAllocation, "-"); @@ -129,9 +132,12 @@ namespace rmv SetModelData(kHeapOverviewCpuVisible, ((segment_status_.flags & kRmtSegmentStatusFlagCpuVisible) != 0) ? "Yes" : "No"); SetModelData(kHeapOverviewGpuCached, ((segment_status_.flags & kRmtSegmentStatusFlagGpuCached) != 0) ? "Yes" : "No"); SetModelData(kHeapOverviewGpuVisible, ((segment_status_.flags & kRmtSegmentStatusFlagGpuVisible) != 0) ? "Yes" : "No"); + SetModelData(kHeapOverviewCommitted, rmv::string_util::LocalizedValueMemory(segment_status_.committed_size, false, false)); + SetModelData(kHeapOverviewAllocationCount, rmv::string_util::LocalizedValue(segment_status_.allocation_count)); SetModelData(kHeapOverviewSmallestAllocation, rmv::string_util::LocalizedValueMemory(segment_status_.min_allocation_size, false, false)); SetModelData(kHeapOverviewLargestAllocation, rmv::string_util::LocalizedValueMemory(segment_status_.max_allocation_size, false, false)); SetModelData(kHeapOverviewMeanAllocation, rmv::string_util::LocalizedValueMemory(segment_status_.mean_allocation_size, false, false)); + SetModelData(kHeapOverviewResourceCount, rmv::string_util::LocalizedValue(segment_status_.resource_count)); } void HeapOverviewHeapModel::GetMemoryParameters(uint64_t& total_physical_size, diff --git a/source/frontend/models/snapshot/heap_overview_heap_model.h b/source/frontend/models/snapshot/heap_overview_heap_model.h index 3ad923d..a5ec368 100644 --- a/source/frontend/models/snapshot/heap_overview_heap_model.h +++ b/source/frontend/models/snapshot/heap_overview_heap_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a model for a heap layout for the Heap Overview pane. @@ -32,9 +32,12 @@ namespace rmv kHeapOverviewCpuVisible, kHeapOverviewGpuCached, kHeapOverviewGpuVisible, + kHeapOverviewAllocationCount, kHeapOverviewSmallestAllocation, kHeapOverviewLargestAllocation, kHeapOverviewMeanAllocation, + kHeapOverviewResourceCount, + kHeapOverviewCommitted, kHeapOverviewNumWidgets, }; diff --git a/source/frontend/models/snapshot/resource_details_model.cpp b/source/frontend/models/snapshot/resource_details_model.cpp index da08887..816022f 100644 --- a/source/frontend/models/snapshot/resource_details_model.cpp +++ b/source/frontend/models/snapshot/resource_details_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the Resource details model. @@ -20,6 +20,7 @@ #include "managers/trace_manager.h" #include "models/colorizer.h" #include "settings/rmv_settings.h" +#include "util/rmv_util.h" #include "util/string_util.h" #include "util/time_util.h" @@ -177,17 +178,8 @@ namespace rmv const char* buf_ptr = &buffer[0]; RmtResourceGetName(resource, RMT_MAXIMUM_NAME_LENGTH, (char**)&buf_ptr); SetModelData(kResourceDetailsResourceName, buffer); - - const uint64_t base_address = (resource->bound_allocation != nullptr) ? resource->bound_allocation->base_address : 0; - if (base_address != 0) - { - SetModelData(kResourceDetailsAllocationBaseAddress, QString("0x") + QString::number(base_address, 16)); - } - else - { - SetModelData(kResourceDetailsAllocationBaseAddress, QString("Orphaned")); - } - SetModelData(kResourceDetailsAllocationOffset, rmv::string_util::LocalizedValue(RmtResourceGetOffsetFromBoundAllocation(resource))); + SetModelData(kResourceDetailsAllocationBaseAddress, rmv_util::GetVirtualAllocationName(resource->bound_allocation)); + SetModelData(kResourceDetailsAllocationOffset, rmv::string_util::LocalizedValueAddress(RmtResourceGetOffsetFromBoundAllocation(resource))); SetModelData(kResourceDetailsBaseAddress, QString("0x") + QString::number(resource->address, 16)); SetModelData(kResourceDetailsSize, rmv::string_util::LocalizedValueMemory(resource->size_in_bytes, false, false)); SetModelData(kResourceDetailsType, RmtGetResourceUsageTypeNameFromResourceUsageType(RmtResourceGetUsageType(resource))); @@ -447,7 +439,7 @@ namespace rmv return true; } - bool ResourceDetailsModel::GetResidencyData(RmtResourceIdentifier resource_identifier, int index, int& value, QString& name, QColor& color) const + bool ResourceDetailsModel::GetResidencyData(RmtResourceIdentifier resource_identifier, int index, float& value, QString& name, QColor& color) const { if (index < 0 || index >= kRmtResourceBackingStorageCount) { @@ -471,10 +463,10 @@ namespace rmv const RmtDataSnapshot* open_snapshot = SnapshotManager::Get().GetOpenSnapshot(); RmtResourceGetBackingStorageHistogram(open_snapshot, resource, memory_segment_histogram); - value = 0; + value = 0.0f; if (resource->size_in_bytes > 0) { - value = (memory_segment_histogram[index] * 100) / resource->size_in_bytes; + value = (memory_segment_histogram[index] * 100.0f) / resource->size_in_bytes; } color = Colorizer::GetHeapColor(static_cast(index)); diff --git a/source/frontend/models/snapshot/resource_details_model.h b/source/frontend/models/snapshot/resource_details_model.h index 7a83286..956c3d9 100644 --- a/source/frontend/models/snapshot/resource_details_model.h +++ b/source/frontend/models/snapshot/resource_details_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Resource details model. @@ -164,7 +164,7 @@ namespace rmv /// @param [out] color The color to use for the heap specified. /// /// @return true if residency data was found, false if error. - bool GetResidencyData(RmtResourceIdentifier resource_identifier, int index, int& value, QString& name, QColor& color) const; + bool GetResidencyData(RmtResourceIdentifier resource_identifier, int index, float& value, QString& name, QColor& color) const; /// @brief Get the data for the unmapped memory. /// diff --git a/source/frontend/models/snapshot/resource_list_model.cpp b/source/frontend/models/snapshot/resource_list_model.cpp index 5d547a8..73eb9da 100644 --- a/source/frontend/models/snapshot/resource_list_model.cpp +++ b/source/frontend/models/snapshot/resource_list_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for Resource List model. @@ -11,6 +11,7 @@ #include "rmt_data_snapshot.h" #include "rmt_print.h" #include "rmt_util.h" +#include "util/rmv_util.h" #include "rmt_virtual_allocation_list.h" #include "managers/trace_manager.h" @@ -124,9 +125,8 @@ namespace rmv void ResourceListModel::FilterBySizeChanged(int min_value, int max_value) { - const SnapshotManager& snapshot_manager = SnapshotManager::Get(); - const uint64_t scaled_min = snapshot_manager.GetSizeFilterThreshold(min_value); - const uint64_t scaled_max = snapshot_manager.GetSizeFilterThreshold(max_value); + const uint64_t scaled_min = rmv_util::CalculateSizeThresholdFromStepValue(min_value, rmv::kSizeSliderRange - 1); + const uint64_t scaled_max = rmv_util::CalculateSizeThresholdFromStepValue(max_value, rmv::kSizeSliderRange - 1); proxy_model_->SetSizeFilter(scaled_min, scaled_max); proxy_model_->invalidate(); diff --git a/source/frontend/models/snapshot/resource_list_model.h b/source/frontend/models/snapshot/resource_list_model.h index 13bede9..aba5eb4 100644 --- a/source/frontend/models/snapshot/resource_list_model.h +++ b/source/frontend/models/snapshot/resource_list_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Resource List model. diff --git a/source/frontend/models/snapshot/resource_overview_model.cpp b/source/frontend/models/snapshot/resource_overview_model.cpp index 2fdb186..3c1310d 100644 --- a/source/frontend/models/snapshot/resource_overview_model.cpp +++ b/source/frontend/models/snapshot/resource_overview_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the Resource Overview model. @@ -14,6 +14,7 @@ #include "rmt_print.h" #include "managers/trace_manager.h" +#include "util/rmv_util.h" #include "util/string_util.h" namespace rmv @@ -52,14 +53,14 @@ namespace rmv } } - void ResourceOverviewModel::FilterBySizeChanged(int32_t min_value, int32_t max_value, bool use_unbound) + void ResourceOverviewModel::FilterBySizeChanged(int32_t min_value, int32_t max_value) { const SnapshotManager& snapshot_manager = SnapshotManager::Get(); const RmtDataSnapshot* open_snapshot = snapshot_manager.GetOpenSnapshot(); if (TraceManager::Get().DataSetValid() && (open_snapshot != nullptr)) { - min_resource_size_ = snapshot_manager.GetSizeFilterThreshold(min_value, use_unbound); - max_resource_size_ = snapshot_manager.GetSizeFilterThreshold(max_value, use_unbound); + min_resource_size_ = rmv_util::CalculateSizeThresholdFromStepValue(min_value, rmv::kSizeSliderRange - 1); + max_resource_size_ = rmv_util::CalculateSizeThresholdFromStepValue(max_value, rmv::kSizeSliderRange - 1); } } @@ -111,12 +112,14 @@ namespace rmv } const uint64_t offset = RmtResourceGetOffsetFromBoundAllocation(resource); - text_string += "\nOffset: " + rmv::string_util::LocalizedValue(offset); + text_string += "\nOffset: " + rmv::string_util::LocalizedValueAddress(offset); const RmtVirtualAllocation* allocation = resource->bound_allocation; if (allocation != nullptr) { - text_string += "\nAllocation " + QString::number(static_cast(allocation->base_address)); + text_string += "\nAllocation " + rmv_util::GetVirtualAllocationName(resource->bound_allocation); + + // A resource identifier of zero signifies that a 'dummy' resource is being used to represent an unbound memory block. if (resource->identifier == 0) { text_string += " (unbound)"; diff --git a/source/frontend/models/snapshot/resource_overview_model.h b/source/frontend/models/snapshot/resource_overview_model.h index 340a660..1ff68e7 100644 --- a/source/frontend/models/snapshot/resource_overview_model.h +++ b/source/frontend/models/snapshot/resource_overview_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Resource Overview model. @@ -40,8 +40,7 @@ namespace rmv /// /// @param [in] min_value Minimum value of slider span. /// @param [in] max_value Maximum value of slider span. - /// @param [in] use_unbound Use unbound resources when considering the size slider. - void FilterBySizeChanged(int32_t min_value, int32_t max_value, bool use_unbound); + void FilterBySizeChanged(int32_t min_value, int32_t max_value); /// @brief Check to see if a resource size is within the slider range. /// diff --git a/source/frontend/models/snapshot/resource_properties_model.cpp b/source/frontend/models/snapshot/resource_properties_model.cpp index 8c2615f..5ef52a9 100644 --- a/source/frontend/models/snapshot/resource_properties_model.cpp +++ b/source/frontend/models/snapshot/resource_properties_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the Resource properties model. @@ -345,5 +345,4 @@ namespace rmv row_index++); return row_index; } - } // namespace rmv \ No newline at end of file diff --git a/source/frontend/models/snapshot/resource_properties_model.h b/source/frontend/models/snapshot/resource_properties_model.h index 8b27b0b..b7600f4 100644 --- a/source/frontend/models/snapshot/resource_properties_model.h +++ b/source/frontend/models/snapshot/resource_properties_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Resource properties model. diff --git a/source/frontend/models/snapshot/resource_timeline_item_model.cpp b/source/frontend/models/snapshot/resource_timeline_item_model.cpp index 8d8313f..bee2aea 100644 --- a/source/frontend/models/snapshot/resource_timeline_item_model.cpp +++ b/source/frontend/models/snapshot/resource_timeline_item_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a resource timeline item model. diff --git a/source/frontend/models/snapshot/resource_timeline_item_model.h b/source/frontend/models/snapshot/resource_timeline_item_model.h index bf4628d..2e348a0 100644 --- a/source/frontend/models/snapshot/resource_timeline_item_model.h +++ b/source/frontend/models/snapshot/resource_timeline_item_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a resource timeline item model. diff --git a/source/frontend/models/timeline/device_configuration_model.cpp b/source/frontend/models/timeline/device_configuration_model.cpp index 91ea371..f833846 100644 --- a/source/frontend/models/timeline/device_configuration_model.cpp +++ b/source/frontend/models/timeline/device_configuration_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the Device configuration model. diff --git a/source/frontend/models/timeline/device_configuration_model.h b/source/frontend/models/timeline/device_configuration_model.h index 4b2b09e..8b160ef 100644 --- a/source/frontend/models/timeline/device_configuration_model.h +++ b/source/frontend/models/timeline/device_configuration_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Device configuration model. diff --git a/source/frontend/models/timeline/snapshot_item_model.cpp b/source/frontend/models/timeline/snapshot_item_model.cpp index 5ffac19..dc4a123 100644 --- a/source/frontend/models/timeline/snapshot_item_model.cpp +++ b/source/frontend/models/timeline/snapshot_item_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a snapshot item model. diff --git a/source/frontend/models/timeline/snapshot_item_model.h b/source/frontend/models/timeline/snapshot_item_model.h index 5cdba80..1612cbf 100644 --- a/source/frontend/models/timeline/snapshot_item_model.h +++ b/source/frontend/models/timeline/snapshot_item_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a snapshot item model. diff --git a/source/frontend/models/timeline/timeline_colorizer.cpp b/source/frontend/models/timeline/timeline_colorizer.cpp index 106e4d1..a7be7dc 100644 --- a/source/frontend/models/timeline/timeline_colorizer.cpp +++ b/source/frontend/models/timeline/timeline_colorizer.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the timeline colorizer control. @@ -17,6 +17,7 @@ #include #include "rmt_assert.h" +#include "rmt_print.h" #include "util/widget_util.h" @@ -93,6 +94,30 @@ namespace rmv ColorizerBase::Initialize(combo_box, legends_view); } + void TimelineColorizer::UpdateLegends() + { + if (color_mode_ == ColorMode::kColorModeResourceUsageType) + { + // Handle special case for TimelineColorizer: hide heap resource type on legend. + legends_scene_->Clear(); + + // Note: Usage types on the legend are drawn in reverse order so that highest aliased priority usage are on the left, lowest on the right. + for (int32_t index = kRmtResourceUsageTypeCount - 1; index > -1; --index) + { + if ((index != RmtResourceUsageType::kRmtResourceUsageTypeUnknown) && (index != RmtResourceUsageType::kRmtResourceUsageTypeHeap)) + { + const RmtResourceUsageType resource_usage_type = (RmtResourceUsageType)index; + legends_scene_->AddColorLegendItem(GetResourceUsageColor(resource_usage_type), + RmtGetResourceUsageTypeNameFromResourceUsageType(resource_usage_type)); + } + } + } + else + { + ColorizerBase::UpdateLegends(legends_scene_, color_mode_); + } + } + RmtDataTimelineType TimelineColorizer::ApplyColorMode(int index) { timeline_type_ = timeline_type_map_[index]; diff --git a/source/frontend/models/timeline/timeline_colorizer.h b/source/frontend/models/timeline/timeline_colorizer.h index c911cd0..13323ba 100644 --- a/source/frontend/models/timeline/timeline_colorizer.h +++ b/source/frontend/models/timeline/timeline_colorizer.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header file for the timeline colorizer control. @@ -54,6 +54,9 @@ namespace rmv /// @return The new timeline type selected. RmtDataTimelineType ApplyColorMode(int index); + /// @brief Override method to update color legends on the UI depending on the coloring mode (hides heap resource type). + virtual void UpdateLegends() Q_DECL_OVERRIDE; + private: RmtDataTimelineType timeline_type_; ///< The timeline type. RmtDataTimelineType timeline_type_map_[kRmtDataTimelineTypeCount]; ///< The mapping of combo box index to timeline type. diff --git a/source/frontend/models/timeline/timeline_model.cpp b/source/frontend/models/timeline/timeline_model.cpp index 38a0277..448e9cf 100644 --- a/source/frontend/models/timeline/timeline_model.cpp +++ b/source/frontend/models/timeline/timeline_model.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the Timeline model. @@ -84,6 +84,7 @@ namespace rmv , max_visible_(0) , histogram_{} , timeline_type_(kRmtDataTimelineTypeResourceUsageVirtualSize) + , is_timeline_generation_in_progress(false) { const RmtErrorCode error_code = RmtJobQueueInitialize(&job_queue_, kThreadCount); RMT_ASSERT(error_code == kRmtOk); @@ -110,6 +111,8 @@ namespace rmv if (trace_manager.DataSetValid()) { + TimelineGenerationBegin(); + // Recreate the timeline for the data set. RmtDataSet* data_set = trace_manager.GetDataSet(); RmtDataTimeline* timeline = trace_manager.GetTimeline(); @@ -119,6 +122,7 @@ namespace rmv error_code = RmtDataSetGenerateTimeline(data_set, timeline_type, timeline); RMT_UNUSED(error_code); RMT_ASSERT_MESSAGE(error_code == kRmtOk, "Error generating new timeline type"); + TimelineGenerationEnd(); } } @@ -278,6 +282,21 @@ namespace rmv return RmtDataSetIsBackgroundTaskCancelled(data_set); } + void TimelineModel::TimelineGenerationBegin() + { + is_timeline_generation_in_progress = true; + } + + void TimelineModel::TimelineGenerationEnd() + { + is_timeline_generation_in_progress = false; + } + + bool TimelineModel::IsTimelineGenerationInProgress() const + { + return is_timeline_generation_in_progress; + } + void TimelineModel::UpdateMemoryGraph(uint64_t min_visible, uint64_t max_visible) { min_visible_ = min_visible; @@ -310,6 +329,38 @@ namespace rmv return kNumBuckets; } + int TimelineModel::RemapBucketGroupNumberToIndex(const int bucket_group_number) const + { + // Lookup table to re-order heap types displayed on the timeline graph. + static int heap_bucket_order_[] = { + RmtHeapType::kRmtHeapTypeSystem, + RmtHeapType::kRmtHeapTypeLocal, + RmtHeapType::kRmtHeapTypeInvisible, + RmtHeapType::kRmtHeapTypeNone, + }; + + // Get the number of heap type items in the lookup table. + static int heap_type_count = static_cast(sizeof(heap_bucket_order_) / sizeof(int)); + int bucket_group_index = bucket_group_number; + RmtDataTimelineType current_timeline_type = histogram_.timeline->timeline_type; + + if ((current_timeline_type == RmtDataTimelineType::kRmtDataTimelineTypeCommitted) || + (current_timeline_type == RmtDataTimelineType::kRmtDataTimelineTypeVirtualMemory)) + { + if ((bucket_group_number < 0) || (bucket_group_number >= heap_type_count)) + { + RMT_ASSERT_MESSAGE(false, "Invalid heap type"); + bucket_group_index = RmtHeapType::kRmtHeapTypeNone; + } + else + { + bucket_group_index = heap_bucket_order_[bucket_group_number]; + } + } + + return bucket_group_index; + } + int TimelineModel::GetNumBucketGroups() const { return histogram_.bucket_group_count; @@ -341,10 +392,11 @@ namespace rmv // Build an array of resource type to count. for (int i = 0; i < GetNumBucketGroups(); i++) { - if (i == kRmtResourceUsageTypeUnknown) + if ((i == kRmtResourceUsageTypeUnknown) || (i == RmtResourceUsageType::kRmtResourceUsageTypeHeap)) { continue; } + sorter.AddResource((RmtResourceUsageType)i, RmtDataTimelineHistogramGetValue(&histogram_, bucket_index, i)); } @@ -370,6 +422,20 @@ namespace rmv color_string += QString("#%1").arg(QString::number(Colorizer::GetResourceUsageColor(kRmtResourceUsageTypeFree).rgb(), 16)); } + void TimelineModel::BuildToolTipInfoString(const RmtHeapType heap_type, const int bucket_index, QString& out_text_string, QString& out_color_string) + { + const int64_t value = RmtDataTimelineHistogramGetValue(&histogram_, bucket_index, heap_type); + if (!out_text_string.isEmpty()) + { + out_text_string += QString("\n"); + out_color_string += QString("\n"); + } + + out_text_string += + QString("%1: %2").arg(RmtGetHeapTypeNameFromHeapType(RmtHeapType(heap_type))).arg(rmv::string_util::LocalizedValueMemory(value, false, false)); + out_color_string += QString("#%1").arg(QString::number(Colorizer::GetHeapColor(static_cast(heap_type)).rgb(), 16)); + } + bool TimelineModel::GetTimelineTooltipInfo(qreal x_pos, QString& text_string, QString& color_string) { int bucket_index = x_pos * kNumBuckets; @@ -387,34 +453,11 @@ namespace rmv break; case kRmtDataTimelineTypeVirtualMemory: - // Calculate memory in each heap. - for (int i = 0; i < GetNumBucketGroups(); i++) - { - int64_t value = RmtDataTimelineHistogramGetValue(&histogram_, bucket_index, i); - if (i > 0) - { - text_string += QString("\n"); - color_string += QString("\n"); - } - text_string += - QString("%1: %2").arg(RmtGetHeapTypeNameFromHeapType(RmtHeapType(i))).arg(rmv::string_util::LocalizedValueMemory(value, false, false)); - color_string += QString("#%1").arg(QString::number(Colorizer::GetHeapColor(static_cast(i)).rgb(), 16)); - } - break; - case kRmtDataTimelineTypeCommitted: - for (int i = 0; i < GetNumBucketGroups(); i++) - { - int64_t value = RmtDataTimelineHistogramGetValue(&histogram_, bucket_index, i); - if (i > 0) - { - text_string += QString("\n"); - color_string += QString("\n"); - } - text_string += - QString("%1: %2").arg(RmtGetHeapTypeNameFromHeapType(RmtHeapType(i))).arg(rmv::string_util::LocalizedValueMemory(value, false, false)); - color_string += QString("#%1").arg(QString::number(Colorizer::GetHeapColor(static_cast(i)).rgb(), 16)); - } + BuildToolTipInfoString(RmtHeapType::kRmtHeapTypeNone, bucket_index, text_string, color_string); + BuildToolTipInfoString(RmtHeapType::kRmtHeapTypeInvisible, bucket_index, text_string, color_string); + BuildToolTipInfoString(RmtHeapType::kRmtHeapTypeLocal, bucket_index, text_string, color_string); + BuildToolTipInfoString(RmtHeapType::kRmtHeapTypeSystem, bucket_index, text_string, color_string); break; default: @@ -424,7 +467,7 @@ namespace rmv return true; } - bool TimelineModel::GetHistogramData(int bucket_group_index, int bucket_index, const int bucket_count, qreal& out_y_pos, qreal& out_height) + bool TimelineModel::GetHistogramData(int bucket_group_number, int bucket_index, const int bucket_group_count, qreal& out_y_pos, qreal& out_height) { if (bucket_index < kNumBuckets) { @@ -437,10 +480,11 @@ namespace rmv out_y_pos = 0.0; qreal histogram_value = 0.0; - if (timeline->timeline_type == kRmtDataTimelineTypeResourceUsageVirtualSize) + if ((timeline->timeline_type == RmtDataTimelineType::kRmtDataTimelineTypeResourceUsageVirtualSize) || + (timeline->timeline_type == RmtDataTimelineType::kRmtDataTimelineTypeResourceUsageCount)) { // For the Resource Usage Size timeline view, reverse the order of the items in the stacked graph. - for (int i = bucket_count; i >= bucket_group_index; i--) + for (int i = bucket_group_count; i >= bucket_group_number; i--) { histogram_value = (double)RmtDataTimelineHistogramGetValue(&histogram_, bucket_index, i); histogram_value /= timeline->maximum_value_in_all_series; @@ -449,9 +493,9 @@ namespace rmv } else { - for (int i = 0; i <= bucket_group_index; i++) + for (int i = 0; i <= bucket_group_number; i++) { - histogram_value = (double)RmtDataTimelineHistogramGetValue(&histogram_, bucket_index, i); + histogram_value = (double)RmtDataTimelineHistogramGetValue(&histogram_, bucket_index, RemapBucketGroupNumberToIndex(i)); histogram_value /= timeline->maximum_value_in_all_series; out_y_pos += histogram_value; } diff --git a/source/frontend/models/timeline/timeline_model.h b/source/frontend/models/timeline/timeline_model.h index 3bcd768..39ebd1a 100644 --- a/source/frontend/models/timeline/timeline_model.h +++ b/source/frontend/models/timeline/timeline_model.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Timeline model. @@ -114,20 +114,27 @@ namespace rmv /// @brief Function to return histogram data. /// - /// @param [in] bucket_group_index The sub-bucket index. - /// @param [in] bucket_index The bucket index. - /// @param [in] bucket_count The total number of buckets. - /// @param [out] out_y_pos The y position offset for this bucket and sub-bucket. - /// @param [out] out_height The height for this bucket and sub-bucket. + /// @param [in] bucket_group_number The sub-bucket number (i.e. stacked bar on the graph). + /// @param [in] bucket_index The bucket index. + /// @param [in] bucket_group_count The total number of buckets in the group. + /// @param [out] out_y_pos The y position offset for this bucket and sub-bucket. + /// @param [out] out_height The height for this bucket and sub-bucket. /// /// @return true if bucket/sub-bucket is valid, false if not. - bool GetHistogramData(int bucket_group_index, int bucket_index, const int bucket_count, qreal& out_y_pos, qreal& out_height); + bool GetHistogramData(int bucket_group_number, int bucket_index, const int bucket_group_count, qreal& out_y_pos, qreal& out_height); /// @brief Get the number of buckets. /// /// @return The number of buckets. int GetNumBuckets() const; + /// @brief Remaps a bucket number to an index ordered as displayed on the graph. + /// + /// @param [in] bucket_group_number The sub-bucket number (i.e. stacked bar on the graph). + /// + /// @return The bucket group index mapped from the bucket group number. + int RemapBucketGroupNumberToIndex(const int bucket_group_number) const; + /// @brief Get the number of grouping modes. /// /// @return The number of grouping modes. @@ -179,6 +186,11 @@ namespace rmv /// @return true if the background task should be cancelled, otherwise false. bool IsBackgroundTaskCancelled() const; + /// @brief Used to determine of background threads are generating the timeline. + /// + /// @return true if the background task is in the process of generating the timeline, otherwise false. + bool IsTimelineGenerationInProgress() const; + private slots: /// @brief Handle what happens when the model data changes. /// @@ -197,6 +209,14 @@ namespace rmv /// @return The value as a string. QString GetValueString(int64_t value, bool display_as_memory) const; + /// @brief Build text and color strings for a tooltip. + /// + /// @param [in] heap_type The type of heap to generate tooltip info for. + /// @param [in] bucket_index The horizontal position on the timeline to retrieve the value for. + /// @param [out] out_text_string The string to receive the tooltip info text (text is appended to existing string). + /// @param [out] out_color_string The string to receive the tooltip coloring (text is appended to existing string). + void BuildToolTipInfoString(const RmtHeapType heap_type, const int bucket_index, QString& out_text_string, QString& out_color_string); + /// @brief Get the resource-specific tool tip Info. /// /// Sort the resources into numerical order and show details in the tooltip (color swatch and text). @@ -207,13 +227,20 @@ namespace rmv /// @param [out] color_string A string to receive the tooltip colors. void GetResourceTooltipInfo(int bucket_index, bool display_as_memory, QString& text_string, QString& color_string); - SnapshotItemModel* table_model_; ///< Holds snapshot table data. - SnapshotTimelineProxyModel* proxy_model_; ///< Table proxy. - uint64_t min_visible_; ///< Minimum visible timestamp. - uint64_t max_visible_; ///< Maximum visible timestamp. - RmtDataTimelineHistogram histogram_; ///< The histogram to render. - RmtDataTimelineType timeline_type_; ///< The timeline type. - RmtJobQueue job_queue_; ///< The job queue. + /// @brief Set the flag that indicates timeline generation is in progress. + void TimelineGenerationBegin(); + + /// @brief Clear the flag that indicates timeline generation is in progress. + void TimelineGenerationEnd(); + + SnapshotItemModel* table_model_; ///< Holds snapshot table data. + SnapshotTimelineProxyModel* proxy_model_; ///< Table proxy. + uint64_t min_visible_; ///< Minimum visible timestamp. + uint64_t max_visible_; ///< Maximum visible timestamp. + RmtDataTimelineHistogram histogram_; ///< The histogram to render. + RmtDataTimelineType timeline_type_; ///< The timeline type. + RmtJobQueue job_queue_; ///< The job queue. + bool is_timeline_generation_in_progress; ///< Indicates, if true, that the timeline is currently being generated. }; } // namespace rmv diff --git a/source/frontend/settings/rmv_geometry_settings.cpp b/source/frontend/settings/rmv_geometry_settings.cpp index 5d346b6..b31d583 100644 --- a/source/frontend/settings/rmv_geometry_settings.cpp +++ b/source/frontend/settings/rmv_geometry_settings.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the geometry settings. diff --git a/source/frontend/settings/rmv_geometry_settings.h b/source/frontend/settings/rmv_geometry_settings.h index 118a145..c0b3989 100644 --- a/source/frontend/settings/rmv_geometry_settings.h +++ b/source/frontend/settings/rmv_geometry_settings.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Define the window geometry settings. diff --git a/source/frontend/settings/rmv_settings.cpp b/source/frontend/settings/rmv_settings.cpp index 6fe54ce..02c3f51 100644 --- a/source/frontend/settings/rmv_settings.cpp +++ b/source/frontend/settings/rmv_settings.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the settings. @@ -88,6 +88,20 @@ namespace rmv } } + bool RMVSettings::DoesFileExistInRecentList(const char* file_path) + { + const int num_recent_files = recent_files_.size(); + for (int loop = 0; loop < num_recent_files; loop++) + { + if (file_path != nullptr && recent_files_[loop].path.compare(file_path) == 0) + { + return true; + } + } + + return false; + } + void RMVSettings::RemoveRecentFile(const QString& trace_name) { const int num_recent_files = this->recent_files_.size(); diff --git a/source/frontend/settings/rmv_settings.h b/source/frontend/settings/rmv_settings.h index 9f27850..e7d9fe9 100644 --- a/source/frontend/settings/rmv_settings.h +++ b/source/frontend/settings/rmv_settings.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Define the settings and information about recently opened traces. @@ -157,6 +157,11 @@ namespace rmv /// @param [in] trace_name The name of the file to remove. void RemoveRecentFile(const QString& trace_name); + /// @brief Determines if a file path exists in recent files list. + /// + /// @return If file is found, returns true. Otherwise returns false. + bool DoesFileExistInRecentList(const char* file_path); + /// @brief Get a reference to the settings. /// /// @return A reference to the settings. diff --git a/source/frontend/settings/settings_reader.cpp b/source/frontend/settings/settings_reader.cpp index 2b74748..9a99ae6 100644 --- a/source/frontend/settings/settings_reader.cpp +++ b/source/frontend/settings/settings_reader.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the XML settings reader. diff --git a/source/frontend/settings/settings_reader.h b/source/frontend/settings/settings_reader.h index aeec6d9..54d7327 100644 --- a/source/frontend/settings/settings_reader.h +++ b/source/frontend/settings/settings_reader.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the XML settings reader. diff --git a/source/frontend/settings/settings_writer.cpp b/source/frontend/settings/settings_writer.cpp index a804ee0..53388cb 100644 --- a/source/frontend/settings/settings_writer.cpp +++ b/source/frontend/settings/settings_writer.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the XML settings writer. diff --git a/source/frontend/settings/settings_writer.h b/source/frontend/settings/settings_writer.h index 878018b..8511834 100644 --- a/source/frontend/settings/settings_writer.h +++ b/source/frontend/settings/settings_writer.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the XML settings writer. diff --git a/source/frontend/stylesheet.qss b/source/frontend/stylesheet.qss index c9b1d59..83e33a6 100644 --- a/source/frontend/stylesheet.qss +++ b/source/frontend/stylesheet.qss @@ -164,6 +164,11 @@ RMVColoredCheckbox /* MainWindow /*************************************/ +MainWindow QWidget#top_spacer_label_ +{ + background-color: rgb(240, 240, 240); +} + MainWindow QWidget#snapshot_label_ { background-color: rgb(240, 240, 240); diff --git a/source/frontend/util/constants.h b/source/frontend/util/constants.h index 09be02b..9219a26 100644 --- a/source/frontend/util/constants.h +++ b/source/frontend/util/constants.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Intended to hold globally-known definitions. @@ -53,7 +53,7 @@ namespace rmv static const int kAllocationHeight = 100; static const int kHeapComboBoxWidth = 140; static const int kResourceComboBoxWidth = 140; - static const int kSizeSliderRange = 100; + static const int kSizeSliderRange = 25; // Control window sizes. static const int kDesktopMargin = 25; @@ -72,17 +72,25 @@ namespace rmv namespace text { + // Generic error message. + static const QString kOpenTraceErrorTitle = "Error"; + static const QString kOpenTraceErrorText = "The trace file, %1, failed to load."; + // Delete recent file pop up dialog. static const QString kDeleteRecentTraceTitle = "Error"; - static const QString kDeleteRecentTraceText = "The trace failed to load. Do you want to remove the trace %1 from the recent files list?"; + static const QString kDeleteRecentTraceText = "\n\nDo you want to remove it from the recent files list?"; + static const QString kRecentTraceAlreadyOpenedTitle = "Warning"; static const QString kRecentTraceAlreadyOpenedText = "Opening the trace file as read-only (snapshot edits will not be saved). The RMV file is either read only or has been opened in another instance " "of RMV"; - // Specific error messages. + // Specific error messages (appended to generic error message). static const QString kOpenTraceOutOfVirtualGPUMemory = - "The trace file contains allocations requesting more than 64GB of GPU memory. Please reduce the video memory consumption.\n\n"; + "\n\nThe trace file contains allocations requesting more than 64GB of GPU memory. Please reduce the video memory consumption."; + + static const QString kOpenTraceFileNotSupported = + "\n\nThe trace file is no longer supported. Please load it using an older version of the Radeon Memory Visualizer."; // Open recent trace missing pop up dialog. static const QString kOpenRecentTraceTitle = "Trace not opened"; diff --git a/source/frontend/util/definitions.h b/source/frontend/util/definitions.h index 7ba2c99..5c6a559 100644 --- a/source/frontend/util/definitions.h +++ b/source/frontend/util/definitions.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Intended to hold globally-known definitions. diff --git a/source/frontend/util/log_file_writer.cpp b/source/frontend/util/log_file_writer.cpp index 0c6ec41..d07fbed 100644 --- a/source/frontend/util/log_file_writer.cpp +++ b/source/frontend/util/log_file_writer.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the LogFileWriter. diff --git a/source/frontend/util/log_file_writer.h b/source/frontend/util/log_file_writer.h index bc4b5b7..1bd03d1 100644 --- a/source/frontend/util/log_file_writer.h +++ b/source/frontend/util/log_file_writer.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Declaration for the log file writer. diff --git a/source/frontend/util/rmv_util.cpp b/source/frontend/util/rmv_util.cpp index b98da31..eb50f0d 100644 --- a/source/frontend/util/rmv_util.cpp +++ b/source/frontend/util/rmv_util.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of rmv_util which holds useful utility functions. @@ -26,6 +26,9 @@ #include "settings/rmv_settings.h" #include "util/version.h" +static const int32_t kThresholdStepOffset = + 7; ///< Used to adjust the unscaled step value when calculating scaled threshold value. + /// @brief Get the brightness of a given color. /// /// Adds weighting values to the color components to compute a color brightness. HSV won't work that well here @@ -165,20 +168,41 @@ QColor rmv_util::GetDeltaChangeColor(DeltaChange delta) return out; } -void rmv_util::BuildResourceSizeThresholds(std::vector& resource_sizes, uint64_t* resource_thresholds) +uint64_t rmv_util::CalculateSizeThresholdFromStepValue(const uint32_t step_value, const uint32_t max_steps) { - if (resource_sizes.size() == 0) + if (step_value == 0) { - return; + return 0; } - std::stable_sort(resource_sizes.begin(), resource_sizes.end()); + if (step_value >= max_steps) + { + return UINT64_MAX; + } - float step_size = (resource_sizes.size() - 1) / static_cast(rmv::kSizeSliderRange); - float index = 0.0F; - for (int loop = 0; loop <= rmv::kSizeSliderRange; loop++) + // Calculate a threshold value ranging from 256 to 1073741824 (1 GB). The lowest step value is 1. + // The threshold offset increases the first step to 8 so that 2 raised to the power of 8 results in a value of 256. + return pow(2, step_value + kThresholdStepOffset); +} + +QString rmv_util::GetVirtualAllocationName(const RmtVirtualAllocation* virtual_allocation) +{ + QString allocation_name; + if (virtual_allocation != nullptr) + { + if (virtual_allocation->name != nullptr) + { + allocation_name = QString("'%1'").arg(virtual_allocation->name); + } + else + { + allocation_name = QString("0x") + QString::number(virtual_allocation->base_address, 16); + } + } + else { - resource_thresholds[loop] = resource_sizes[static_cast(round(index))]; - index += step_size; + allocation_name = "Orphaned"; } + + return allocation_name; } diff --git a/source/frontend/util/rmv_util.h b/source/frontend/util/rmv_util.h index b74c2c6..97ef494 100644 --- a/source/frontend/util/rmv_util.h +++ b/source/frontend/util/rmv_util.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for rmv_util which holds useful utility functions. @@ -10,6 +10,7 @@ #include +#include "rmt_virtual_allocation_list.h" #include "util/definitions.h" /// @brief The state of a snapshot in the timeline pane. @@ -75,11 +76,20 @@ namespace rmv_util /// @return a QColor assigned to the delta type. QColor GetDeltaChangeColor(DeltaChange delta); - /// @brief Build a list of resource thresholds used by the 'filter by size' slider. + /// @brief Calculate the logarithmically scaled value given a step value. /// - /// @param [in] resource_sizes An vector containing a list of resource sizes. - /// @param [in] resource_thresholds An array to accept the resource thresholds. - void BuildResourceSizeThresholds(std::vector& resource_sizes, uint64_t* resource_thresholds); + /// @param [in] step_value An unscaled whole number used to calculate a scaled threshold value. + /// @param [in] max_steps The maximum number of steps in the range. + /// + /// @return The calculated value. + uint64_t CalculateSizeThresholdFromStepValue(const uint32_t step_value, const uint32_t max_steps); + + /// @brief Retrieves the name of a virtual allocation or a string containing the base address in hexadecimal form. + /// + /// @param [in] virtual_allocation A pointer to the virtual allocation object. + /// + /// @return The virtual allocation name string. + QString GetVirtualAllocationName(const RmtVirtualAllocation* virtual_allocation); }; // namespace rmv_util diff --git a/source/frontend/util/string_util.cpp b/source/frontend/util/string_util.cpp index a2e136a..4ceb30d 100644 --- a/source/frontend/util/string_util.cpp +++ b/source/frontend/util/string_util.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a number of string utilities. @@ -69,7 +69,7 @@ QString rmv::string_util::LocalizedValuePrecise(double value) return str; } -QString rmv::string_util::LocalizedValueMemory(double value, bool base_10, bool use_round) +QString rmv::string_util::LocalizedValueMemory(const double value, const bool base_10, const bool use_round, const bool include_decimal) { double multiple; if (base_10) @@ -107,7 +107,7 @@ QString rmv::string_util::LocalizedValueMemory(double value, bool base_10, bool // Display value string to 2 decimal places if not bytes. No fractional part for bytes. QString value_string; - if (postfix_index != 0) + if ((postfix_index != 0) && (include_decimal)) { value_string = LocalizedValuePrecise(scaled_size); } @@ -136,3 +136,42 @@ QString rmv::string_util::LocalizedValueBytes(int64_t value) { return rmv::string_util::LocalizedValue(value) + " bytes"; } + +QString rmv::string_util::GetMemoryRangeString(const uint64_t min_memory_size, const uint64_t max_memory_size) +{ + const static char kHyphen[] = " - "; + const static char kInfinity[] = "\xE2\x88\x9E"; + QString range_string; + int width = 0; + + // Append string for range start. + if (min_memory_size == UINT64_MAX) + { + range_string += kInfinity; + width++; + } + else + { + QString value = string_util::LocalizedValueMemory(min_memory_size, false, false, false); + width += value.length(); + range_string += value; + } + + range_string += kHyphen; + width += sizeof(kHyphen); + + // Append string for range end. + if (max_memory_size == UINT64_MAX) + { + range_string += kInfinity; + width++; + } + else + { + QString value = string_util::LocalizedValueMemory(max_memory_size, false, false, false); + width += value.length(); + range_string += value; + } + + return range_string; +} diff --git a/source/frontend/util/string_util.h b/source/frontend/util/string_util.h index 4716340..c4b34b7 100644 --- a/source/frontend/util/string_util.h +++ b/source/frontend/util/string_util.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of a number of string utilities. @@ -55,11 +55,13 @@ namespace rmv /// be selected. Base 2 uses 1024 rather than 1000. Units are appended to /// display XB for base 10 or XiB for base 2. /// - /// @param [in] value The value to display. - /// @param [in] base_10 If true, use base 10 values, otherwise base 2. + /// @param [in] value The value to display. + /// @param [in] base_10 If true, use base 10 values, otherwise base 2. + /// @param [in] use_round If true and units aren't in bytes, round up the value. + /// @param [in] include_decimal If true, include the fractional part of the value. /// /// @return The localized string. - QString LocalizedValueMemory(double value, bool base_10, bool use_round); + QString LocalizedValueMemory(const double value, const bool base_10, const bool use_round, const bool include_decimal = true); /// @brief Format an address for printing. /// @@ -77,6 +79,14 @@ namespace rmv /// @return The localized string. QString LocalizedValueBytes(int64_t value); + /// @brief Builds a range string for the memory size thresholds. + /// + /// @param [in] min_memory_size The lower value of the range. + /// @param [in] max_memory_size The upper value of the range. + /// + /// @return The localized string. + QString GetMemoryRangeString(const uint64_t min_memory_size, const uint64_t max_memory_size); + } // namespace string_util } // namespace rmv diff --git a/source/frontend/util/thread_controller.cpp b/source/frontend/util/thread_controller.cpp index acb35f0..a8d67c4 100644 --- a/source/frontend/util/thread_controller.cpp +++ b/source/frontend/util/thread_controller.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a thread controller. diff --git a/source/frontend/util/thread_controller.h b/source/frontend/util/thread_controller.h index 30e2f2c..a02ed53 100644 --- a/source/frontend/util/thread_controller.h +++ b/source/frontend/util/thread_controller.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a thread controller. diff --git a/source/frontend/util/time_util.cpp b/source/frontend/util/time_util.cpp index cba5809..aa582a4 100644 --- a/source/frontend/util/time_util.cpp +++ b/source/frontend/util/time_util.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a number of time-related utilities. diff --git a/source/frontend/util/time_util.h b/source/frontend/util/time_util.h index 86232ce..1e9525c 100644 --- a/source/frontend/util/time_util.h +++ b/source/frontend/util/time_util.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of a number of time-related utilities. diff --git a/source/frontend/util/version.cpp b/source/frontend/util/version.cpp index 4837ae5..4e918a3 100644 --- a/source/frontend/util/version.cpp +++ b/source/frontend/util/version.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Version number info for RMV diff --git a/source/frontend/util/widget_util.cpp b/source/frontend/util/widget_util.cpp index a594bfe..6e5f8c4 100644 --- a/source/frontend/util/widget_util.cpp +++ b/source/frontend/util/widget_util.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a number of widget utilities. @@ -18,14 +18,14 @@ namespace rmv { - void widget_util::InitDoubleSlider(DoubleSliderWidget* double_slider_widget) + void widget_util::InitRangeSlider(RmvRangeSlider* slider_widget) { - double_slider_widget->setFixedWidth(ScalingManager::Get().Scaled(rmv::kDoubleSliderWidth)); - double_slider_widget->setFixedHeight(ScalingManager::Get().Scaled(rmv::kDoubleSliderHeight)); - double_slider_widget->setCursor(Qt::PointingHandCursor); - double_slider_widget->setMinimum(0); - double_slider_widget->setMaximum(kSizeSliderRange); - double_slider_widget->Init(); + slider_widget->setFixedWidth(ScalingManager::Get().Scaled(rmv::kDoubleSliderWidth)); + slider_widget->setFixedHeight(ScalingManager::Get().Scaled(rmv::kDoubleSliderHeight)); + slider_widget->setCursor(Qt::PointingHandCursor); + slider_widget->setMinimum(0); + slider_widget->setMaximum(kSizeSliderRange - 1); + slider_widget->Init(); } void widget_util::InitSingleSelectComboBox(QWidget* parent, diff --git a/source/frontend/util/widget_util.h b/source/frontend/util/widget_util.h index 955ce53..eb21eb0 100644 --- a/source/frontend/util/widget_util.h +++ b/source/frontend/util/widget_util.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of a number of widget utilities. @@ -11,6 +11,8 @@ #ifndef RMV_UTIL_WIDGET_UTIL_H_ #define RMV_UTIL_WIDGET_UTIL_H_ +#include "views/custom_widgets/rmv_range_slider.h" + #include #include #include @@ -18,7 +20,6 @@ #include #include "qt_common/custom_widgets/text_search_widget.h" -#include "qt_common/custom_widgets/double_slider_widget.h" #include "qt_common/custom_widgets/arrow_icon_combo_box.h" #include "qt_common/custom_widgets/colored_legend_scene.h" @@ -26,10 +27,10 @@ namespace rmv { namespace widget_util { - /// @brief Initialize a double-slider widget. + /// @brief Initialize a range slider widget. /// - /// @param [in,out] double_slider_widget The slider to initialize - void InitDoubleSlider(DoubleSliderWidget* double_slider_widget); + /// @param [in,out] range_slider A pointer to the RmvRangeSlider widget to initialize. + void InitRangeSlider(RmvRangeSlider* slider_widget); /// @brief Initialize an ArrowIconComboBox for single selection. /// diff --git a/source/frontend/views/base_pane.cpp b/source/frontend/views/base_pane.cpp index 11a2cf0..b8acea9 100644 --- a/source/frontend/views/base_pane.cpp +++ b/source/frontend/views/base_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a base pane class. diff --git a/source/frontend/views/base_pane.h b/source/frontend/views/base_pane.h index 04f093d..1f62827 100644 --- a/source/frontend/views/base_pane.h +++ b/source/frontend/views/base_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the base pane class. diff --git a/source/frontend/views/compare/compare_start_pane.cpp b/source/frontend/views/compare/compare_start_pane.cpp index 4a7ddc7..9815f10 100644 --- a/source/frontend/views/compare/compare_start_pane.cpp +++ b/source/frontend/views/compare/compare_start_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of Compare start pane. diff --git a/source/frontend/views/compare/compare_start_pane.h b/source/frontend/views/compare/compare_start_pane.h index d2add5e..81adc2a 100644 --- a/source/frontend/views/compare/compare_start_pane.h +++ b/source/frontend/views/compare/compare_start_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Compare start pane. diff --git a/source/frontend/views/compare/memory_leak_finder_pane.cpp b/source/frontend/views/compare/memory_leak_finder_pane.cpp index 48e295f..bb45d93 100644 --- a/source/frontend/views/compare/memory_leak_finder_pane.cpp +++ b/source/frontend/views/compare/memory_leak_finder_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Memory leak finder pane. @@ -43,6 +43,7 @@ MemoryLeakFinderPane::MemoryLeakFinderPane(QWidget* parent) model_->InitializeTableModel(ui_->resource_table_view_, 0, rmv::kResourceColumnCount, rmv::kSnapshotCompareIdCommon); ui_->resource_table_view_->setCursor(Qt::PointingHandCursor); + ui_->resource_table_view_->sortByColumn(rmv::kResourceColumnVirtualAddress, Qt::AscendingOrder); rmv::widget_util::InitMultiSelectComboBox(this, ui_->preferred_heap_combo_box_, rmv::text::kPreferredHeap); rmv::widget_util::InitMultiSelectComboBox(this, ui_->resource_usage_combo_box_, rmv::text::kResourceUsage); @@ -62,6 +63,7 @@ MemoryLeakFinderPane::MemoryLeakFinderPane(QWidget* parent) ui_->resource_table_view_->verticalHeader()->setDefaultSectionSize(compare_id_delegate_->DefaultSizeHint().height()); rmv::widget_util::InitCommonFilteringComponents(ui_->search_box_, ui_->size_slider_); + rmv::widget_util::InitRangeSlider(ui_->size_slider_); ui_->base_allocations_checkbox_->Initialize(false, rmv::RMVSettings::Get().GetColorSnapshotViewed(), Qt::black); ui_->both_allocations_checkbox_->Initialize( @@ -81,6 +83,8 @@ MemoryLeakFinderPane::MemoryLeakFinderPane(QWidget* parent) // Set up a connection between the timeline being sorted and making sure the selected event is visible. connect(model_->GetResourceProxyModel(), &rmv::MemoryLeakFinderProxyModel::layoutChanged, this, &MemoryLeakFinderPane::ScrollToSelectedResource); + connect(&rmv::MessageManager::Get(), &rmv::MessageManager::SwapSnapshotsRequested, this, &MemoryLeakFinderPane::SwitchSnapshots); + connect(&ScalingManager::Get(), &ScalingManager::ScaleFactorChanged, this, &MemoryLeakFinderPane::OnScaleFactorChanged); } @@ -97,7 +101,7 @@ MemoryLeakFinderPane::~MemoryLeakFinderPane() void MemoryLeakFinderPane::showEvent(QShowEvent* event) { HeapChanged(false); - ResourceChanged(false); + ResourceChanged(false, -1); Update(false); QWidget::showEvent(event); @@ -116,6 +120,15 @@ void MemoryLeakFinderPane::OnScaleFactorChanged() ui_->resource_table_view_->verticalHeader()->setDefaultSectionSize(checkmark_icon_height); } +void MemoryLeakFinderPane::SwitchSnapshots() +{ + const rmv::SnapshotCompareId compare_filter = GetCompareIdFilter(); + if (model_->SwapSnapshots(compare_filter) == true) + { + Update(false); + } +} + void MemoryLeakFinderPane::Refresh() { Update(true); @@ -160,8 +173,6 @@ void MemoryLeakFinderPane::Update(bool reset_filters) ui_->resource_table_view_->setSortingEnabled(true); - ui_->resource_table_view_->sortByColumn(rmv::kResourceColumnName, Qt::DescendingOrder); - SetMaximumResourceTableHeight(); } @@ -176,7 +187,7 @@ void MemoryLeakFinderPane::Reset() model_->ResetModelValues(); ui_->size_slider_->SetLowerValue(0); - ui_->size_slider_->SetUpperValue(rmv::kSizeSliderRange); + ui_->size_slider_->SetUpperValue(ui_->size_slider_->maximum()); ui_->search_box_->setText(""); } @@ -215,11 +226,12 @@ void MemoryLeakFinderPane::HeapChanged(bool checked) SetMaximumResourceTableHeight(); } -void MemoryLeakFinderPane::ResourceChanged(bool checked) +void MemoryLeakFinderPane::ResourceChanged(bool checked, int changed_item_index) { - // Rebuild the table depending on what the state of the combo box items is. RMT_UNUSED(checked); + // Rebuild the table depending on what the state of the combo box items is. + resource_usage_combo_box_model_->UpdateCheckboxes(changed_item_index, ui_->resource_usage_combo_box_); QString filter_string = resource_usage_combo_box_model_->GetFilterString(ui_->resource_usage_combo_box_); model_->UpdateResourceUsageList(filter_string); SetMaximumResourceTableHeight(); diff --git a/source/frontend/views/compare/memory_leak_finder_pane.h b/source/frontend/views/compare/memory_leak_finder_pane.h index b28b184..bb053a4 100644 --- a/source/frontend/views/compare/memory_leak_finder_pane.h +++ b/source/frontend/views/compare/memory_leak_finder_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Memory leak finder pane. @@ -80,8 +80,9 @@ private slots: /// @brief Handle what happens when a checkbox in the resource dropdown is checked or unchecked. /// - /// @param [in] checked Whether the checkbox is checked or unchecked. - void ResourceChanged(bool checked); + /// @param [in] checked Whether the checkbox is checked or unchecked. + /// @param [in] changed_item_index The index of the checkbox in the combo box that was changed. + void ResourceChanged(bool checked, int changed_item_index); /// @brief Slot to handle what happens when a resource in the table is double-clicked on. /// @@ -90,6 +91,9 @@ private slots: /// @param [in] index the model index of the selected item in the table. void TableDoubleClicked(const QModelIndex& index); + /// @brief Switch snapshots. + void SwitchSnapshots(); + private: /// @brief Refresh what's visible on the UI. /// diff --git a/source/frontend/views/compare/memory_leak_finder_pane.ui b/source/frontend/views/compare/memory_leak_finder_pane.ui index a9895e6..91c4813 100644 --- a/source/frontend/views/compare/memory_leak_finder_pane.ui +++ b/source/frontend/views/compare/memory_leak_finder_pane.ui @@ -345,7 +345,7 @@ - + Qt::Horizontal @@ -509,9 +509,9 @@
qt_common/custom_widgets/text_search_widget.h
- DoubleSliderWidget + RmvRangeSlider QSlider -
qt_common/custom_widgets/double_slider_widget.h
+
views/custom_widgets/rmv_range_slider.h
ScaledTableView diff --git a/source/frontend/views/compare/snapshot_delta_pane.cpp b/source/frontend/views/compare/snapshot_delta_pane.cpp index fb048dd..2d62160 100644 --- a/source/frontend/views/compare/snapshot_delta_pane.cpp +++ b/source/frontend/views/compare/snapshot_delta_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Snapshot delta pane. @@ -9,6 +9,7 @@ #include "qt_common/utils/scaling_manager.h" +#include "managers/message_manager.h" #include "util/rmv_util.h" #include "util/widget_util.h" @@ -67,7 +68,8 @@ SnapshotDeltaPane::SnapshotDeltaPane(QWidget* parent) ui_->legends_view_->setFixedSize(legend_rect.toRect().size()); ui_->legends_view_->setSceneRect(legend_rect); - connect(ui_->switch_button_, &QPushButton::pressed, this, &SnapshotDeltaPane::SwitchSnapshots); + connect(ui_->switch_button_, &QPushButton::pressed, [=]() { emit rmv::MessageManager::Get().SwapSnapshotsRequested(); }); + connect(&rmv::MessageManager::Get(), &rmv::MessageManager::SwapSnapshotsRequested, this, &SnapshotDeltaPane::SwitchSnapshots); connect(&ScalingManager::Get(), &ScalingManager::ScaleFactorChanged, this, &SnapshotDeltaPane::OnScaleFactorChanged); } diff --git a/source/frontend/views/compare/snapshot_delta_pane.h b/source/frontend/views/compare/snapshot_delta_pane.h index 1f280ca..593e8a2 100644 --- a/source/frontend/views/compare/snapshot_delta_pane.h +++ b/source/frontend/views/compare/snapshot_delta_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Snapshot Delta pane. diff --git a/source/frontend/views/compare_pane.cpp b/source/frontend/views/compare_pane.cpp index cb446a3..11a42f2 100644 --- a/source/frontend/views/compare_pane.cpp +++ b/source/frontend/views/compare_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2021-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the compare pane base class. diff --git a/source/frontend/views/compare_pane.h b/source/frontend/views/compare_pane.h index c367f38..a8bae09 100644 --- a/source/frontend/views/compare_pane.h +++ b/source/frontend/views/compare_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2021-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the compare pane base class. diff --git a/source/frontend/views/custom_widgets/rmv_allocation_bar.cpp b/source/frontend/views/custom_widgets/rmv_allocation_bar.cpp index d03f389..0e13490 100644 --- a/source/frontend/views/custom_widgets/rmv_allocation_bar.cpp +++ b/source/frontend/views/custom_widgets/rmv_allocation_bar.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of an allocation graphics object. diff --git a/source/frontend/views/custom_widgets/rmv_allocation_bar.h b/source/frontend/views/custom_widgets/rmv_allocation_bar.h index 68ec9ec..6291a1e 100644 --- a/source/frontend/views/custom_widgets/rmv_allocation_bar.h +++ b/source/frontend/views/custom_widgets/rmv_allocation_bar.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for an allocation graphics object. diff --git a/source/frontend/views/custom_widgets/rmv_camera_snapshot_widget.cpp b/source/frontend/views/custom_widgets/rmv_camera_snapshot_widget.cpp index 9fc7bb5..bd5e922 100644 --- a/source/frontend/views/custom_widgets/rmv_camera_snapshot_widget.cpp +++ b/source/frontend/views/custom_widgets/rmv_camera_snapshot_widget.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a camera snapshot widget. diff --git a/source/frontend/views/custom_widgets/rmv_camera_snapshot_widget.h b/source/frontend/views/custom_widgets/rmv_camera_snapshot_widget.h index f013765..12a247b 100644 --- a/source/frontend/views/custom_widgets/rmv_camera_snapshot_widget.h +++ b/source/frontend/views/custom_widgets/rmv_camera_snapshot_widget.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a camera snapshot widget. diff --git a/source/frontend/views/custom_widgets/rmv_cancellable_loading_widget.cpp b/source/frontend/views/custom_widgets/rmv_cancellable_loading_widget.cpp index 4ea3d09..d6328da 100644 --- a/source/frontend/views/custom_widgets/rmv_cancellable_loading_widget.cpp +++ b/source/frontend/views/custom_widgets/rmv_cancellable_loading_widget.cpp @@ -1,5 +1,5 @@ //============================================================================= -/// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +/// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// \author AMD Developer Tools Team /// \file /// \brief Implementation of a loading widget with a cancel button. diff --git a/source/frontend/views/custom_widgets/rmv_cancellable_loading_widget.h b/source/frontend/views/custom_widgets/rmv_cancellable_loading_widget.h index a23b534..4e61a12 100644 --- a/source/frontend/views/custom_widgets/rmv_cancellable_loading_widget.h +++ b/source/frontend/views/custom_widgets/rmv_cancellable_loading_widget.h @@ -1,5 +1,5 @@ //============================================================================= -/// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +/// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// \author AMD Developer Tools Team /// \file /// \brief Header for a loading widget that has a cancel button diff --git a/source/frontend/views/custom_widgets/rmv_carousel.cpp b/source/frontend/views/custom_widgets/rmv_carousel.cpp index 4ce5141..6307810 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel.cpp +++ b/source/frontend/views/custom_widgets/rmv_carousel.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the carousel. diff --git a/source/frontend/views/custom_widgets/rmv_carousel.h b/source/frontend/views/custom_widgets/rmv_carousel.h index af245cb..4ca1a60 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel.h +++ b/source/frontend/views/custom_widgets/rmv_carousel.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the carousel. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_allocation_sizes.cpp b/source/frontend/views/custom_widgets/rmv_carousel_allocation_sizes.cpp index 057dbbf..c205f2c 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_allocation_sizes.cpp +++ b/source/frontend/views/custom_widgets/rmv_carousel_allocation_sizes.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the carousel allocation sizes widget. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_allocation_sizes.h b/source/frontend/views/custom_widgets/rmv_carousel_allocation_sizes.h index 321a92b..d1efcd7 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_allocation_sizes.h +++ b/source/frontend/views/custom_widgets/rmv_carousel_allocation_sizes.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the carousel allocation sizes widget. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_item.cpp b/source/frontend/views/custom_widgets/rmv_carousel_item.cpp index d6a65af..2d9b4f2 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_item.cpp +++ b/source/frontend/views/custom_widgets/rmv_carousel_item.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the carousel item widget base class. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_item.h b/source/frontend/views/custom_widgets/rmv_carousel_item.h index f5cd040..0a4b8c6 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_item.h +++ b/source/frontend/views/custom_widgets/rmv_carousel_item.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the carousel item widget base class. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_memory_footprint.cpp b/source/frontend/views/custom_widgets/rmv_carousel_memory_footprint.cpp index 14a086c..51f1498 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_memory_footprint.cpp +++ b/source/frontend/views/custom_widgets/rmv_carousel_memory_footprint.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the carousel memory footprint widget. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_memory_footprint.h b/source/frontend/views/custom_widgets/rmv_carousel_memory_footprint.h index 93e1fa4..ed4938d 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_memory_footprint.h +++ b/source/frontend/views/custom_widgets/rmv_carousel_memory_footprint.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the carousel memory footprint widget. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_memory_types.cpp b/source/frontend/views/custom_widgets/rmv_carousel_memory_types.cpp index 082e93a..8246544 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_memory_types.cpp +++ b/source/frontend/views/custom_widgets/rmv_carousel_memory_types.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the carousel memory types widget. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_memory_types.h b/source/frontend/views/custom_widgets/rmv_carousel_memory_types.h index a5f2409..a0eed23 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_memory_types.h +++ b/source/frontend/views/custom_widgets/rmv_carousel_memory_types.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the carousel memory types widget. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_nav_button.cpp b/source/frontend/views/custom_widgets/rmv_carousel_nav_button.cpp index edff39f..090645d 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_nav_button.cpp +++ b/source/frontend/views/custom_widgets/rmv_carousel_nav_button.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the carousel navigation button. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_nav_button.h b/source/frontend/views/custom_widgets/rmv_carousel_nav_button.h index f82c3ad..3e08a29 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_nav_button.h +++ b/source/frontend/views/custom_widgets/rmv_carousel_nav_button.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the carousel navigation button. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_resource_types.cpp b/source/frontend/views/custom_widgets/rmv_carousel_resource_types.cpp index 4064914..19e7146 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_resource_types.cpp +++ b/source/frontend/views/custom_widgets/rmv_carousel_resource_types.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the carousel resource types widget. diff --git a/source/frontend/views/custom_widgets/rmv_carousel_resource_types.h b/source/frontend/views/custom_widgets/rmv_carousel_resource_types.h index 8209e05..973b08f 100644 --- a/source/frontend/views/custom_widgets/rmv_carousel_resource_types.h +++ b/source/frontend/views/custom_widgets/rmv_carousel_resource_types.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the carousel resource types widget. diff --git a/source/frontend/views/custom_widgets/rmv_color_picker_button.cpp b/source/frontend/views/custom_widgets/rmv_color_picker_button.cpp index 0425bb4..d6d2cbc 100644 --- a/source/frontend/views/custom_widgets/rmv_color_picker_button.cpp +++ b/source/frontend/views/custom_widgets/rmv_color_picker_button.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2021-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a color picker button. diff --git a/source/frontend/views/custom_widgets/rmv_color_picker_button.h b/source/frontend/views/custom_widgets/rmv_color_picker_button.h index 343e5bb..1538c53 100644 --- a/source/frontend/views/custom_widgets/rmv_color_picker_button.h +++ b/source/frontend/views/custom_widgets/rmv_color_picker_button.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2021-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a color picker button. diff --git a/source/frontend/views/custom_widgets/rmv_color_picker_widget.cpp b/source/frontend/views/custom_widgets/rmv_color_picker_widget.cpp index 0ba8c66..6c6daa2 100644 --- a/source/frontend/views/custom_widgets/rmv_color_picker_widget.cpp +++ b/source/frontend/views/custom_widgets/rmv_color_picker_widget.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a color picker widget. diff --git a/source/frontend/views/custom_widgets/rmv_color_picker_widget.h b/source/frontend/views/custom_widgets/rmv_color_picker_widget.h index 945d412..b02981d 100644 --- a/source/frontend/views/custom_widgets/rmv_color_picker_widget.h +++ b/source/frontend/views/custom_widgets/rmv_color_picker_widget.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a color picker widget. diff --git a/source/frontend/views/custom_widgets/rmv_color_swatch_tooltip_item.cpp b/source/frontend/views/custom_widgets/rmv_color_swatch_tooltip_item.cpp index cc5a1f3..d5788c6 100644 --- a/source/frontend/views/custom_widgets/rmv_color_swatch_tooltip_item.cpp +++ b/source/frontend/views/custom_widgets/rmv_color_swatch_tooltip_item.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a custom tooltip comprising of a multiline diff --git a/source/frontend/views/custom_widgets/rmv_color_swatch_tooltip_item.h b/source/frontend/views/custom_widgets/rmv_color_swatch_tooltip_item.h index 114bcb9..61fa108 100644 --- a/source/frontend/views/custom_widgets/rmv_color_swatch_tooltip_item.h +++ b/source/frontend/views/custom_widgets/rmv_color_swatch_tooltip_item.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a custom tooltip comprising of a multiline text diff --git a/source/frontend/views/custom_widgets/rmv_colored_checkbox.cpp b/source/frontend/views/custom_widgets/rmv_colored_checkbox.cpp index ff44b23..8cc6324 100644 --- a/source/frontend/views/custom_widgets/rmv_colored_checkbox.cpp +++ b/source/frontend/views/custom_widgets/rmv_colored_checkbox.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a widget that implements a custom check box. diff --git a/source/frontend/views/custom_widgets/rmv_colored_checkbox.h b/source/frontend/views/custom_widgets/rmv_colored_checkbox.h index 0628ccb..18251c3 100644 --- a/source/frontend/views/custom_widgets/rmv_colored_checkbox.h +++ b/source/frontend/views/custom_widgets/rmv_colored_checkbox.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header of a widget that implements a custom check box. diff --git a/source/frontend/views/custom_widgets/rmv_delta_display.cpp b/source/frontend/views/custom_widgets/rmv_delta_display.cpp index 1b26969..cc4d0b1 100644 --- a/source/frontend/views/custom_widgets/rmv_delta_display.cpp +++ b/source/frontend/views/custom_widgets/rmv_delta_display.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a graphics view that implements data delta. diff --git a/source/frontend/views/custom_widgets/rmv_delta_display.h b/source/frontend/views/custom_widgets/rmv_delta_display.h index 001812e..cd420f4 100644 --- a/source/frontend/views/custom_widgets/rmv_delta_display.h +++ b/source/frontend/views/custom_widgets/rmv_delta_display.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a graphics view that implements data delta. diff --git a/source/frontend/views/custom_widgets/rmv_delta_display_widget.cpp b/source/frontend/views/custom_widgets/rmv_delta_display_widget.cpp index e72b8e8..c27fb64 100644 --- a/source/frontend/views/custom_widgets/rmv_delta_display_widget.cpp +++ b/source/frontend/views/custom_widgets/rmv_delta_display_widget.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a delta display widget. diff --git a/source/frontend/views/custom_widgets/rmv_delta_display_widget.h b/source/frontend/views/custom_widgets/rmv_delta_display_widget.h index fe20056..5be2513 100644 --- a/source/frontend/views/custom_widgets/rmv_delta_display_widget.h +++ b/source/frontend/views/custom_widgets/rmv_delta_display_widget.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a delta display widget. diff --git a/source/frontend/views/custom_widgets/rmv_fixed_width_label.cpp b/source/frontend/views/custom_widgets/rmv_fixed_width_label.cpp new file mode 100644 index 0000000..d153e2c --- /dev/null +++ b/source/frontend/views/custom_widgets/rmv_fixed_width_label.cpp @@ -0,0 +1,33 @@ +//============================================================================= +/// Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief Implementation for the fixed width label widget. +//============================================================================= + +#include "views/custom_widgets/rmv_fixed_width_label.h" + +RmvFixedWidthLabel::RmvFixedWidthLabel(QWidget* parent) + : ScaledLabel(parent) +{ + setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); +} + +RmvFixedWidthLabel::~RmvFixedWidthLabel() +{ +} + +void RmvFixedWidthLabel::SetWidestTextString(const QString& string) +{ + widest_text_string_ = string; +} + +QSize RmvFixedWidthLabel::sizeHint() const +{ + QSize size = ScaledLabel::sizeHint(); + const QFontMetrics fm(font()); + const int width = fm.horizontalAdvance(widest_text_string_); + size.setWidth(width); + + return size; +} diff --git a/source/frontend/views/custom_widgets/rmv_fixed_width_label.h b/source/frontend/views/custom_widgets/rmv_fixed_width_label.h new file mode 100644 index 0000000..de5e2b5 --- /dev/null +++ b/source/frontend/views/custom_widgets/rmv_fixed_width_label.h @@ -0,0 +1,37 @@ +//============================================================================= +/// Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief Header for the fixed width label widget. +//============================================================================= + +#ifndef RMV_VIEWS_CUSTOM_WIDGETS_RMV_FIXED_WIDTH_LABEL_H_ +#define RMV_VIEWS_CUSTOM_WIDGETS_RMV_FIXED_WIDTH_LABEL_H_ + +#include "qt_common/custom_widgets/scaled_label.h" + +/// Reimplements the scaled label to have a fixed width. +class RmvFixedWidthLabel : public ScaledLabel +{ + Q_OBJECT + +public: + /// Constructor + /// \param parent The parent widget + RmvFixedWidthLabel(QWidget* parent); + + /// Virtual destructor + virtual ~RmvFixedWidthLabel(); + + void SetWidestTextString(const QString& string); + + /// @brief Provide a sizeHint with a fixed width to match the size of the longest expected string. + /// + /// @return The desired size of the widget. + QSize sizeHint() const Q_DECL_OVERRIDE; + +private: + QString widest_text_string_; ///< A string representing the longest expected width. +}; + +#endif // RMV_VIEWS_CUSTOM_WIDGETS_RMV_FIXED_WIDTH_LABEL_H_ diff --git a/source/frontend/views/custom_widgets/rmv_heap_overview_memory_bar.cpp b/source/frontend/views/custom_widgets/rmv_heap_overview_memory_bar.cpp index f80ca6f..05e6f9c 100644 --- a/source/frontend/views/custom_widgets/rmv_heap_overview_memory_bar.cpp +++ b/source/frontend/views/custom_widgets/rmv_heap_overview_memory_bar.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a heap overview memory bar. @@ -18,6 +18,7 @@ static const QColor kGrayProcessColor = QColor(128, 128, 128); static const QColor kGrayOtherProcessColor = QColor(184, 184, 184); +static const QColor kEmphasizedBarColor = QColor(192, 192, 192); RMVHeapOverviewMemoryBar::RMVHeapOverviewMemoryBar(QWidget* parent) : QWidget(parent) @@ -26,6 +27,7 @@ RMVHeapOverviewMemoryBar::RMVHeapOverviewMemoryBar(QWidget* parent) , max_size_(0) , has_subscription_(false) , subscription_status_(kRmtSegmentSubscriptionStatusUnderLimit) + , emphasize_(false) { } @@ -63,7 +65,7 @@ void RMVHeapOverviewMemoryBar::paintEvent(QPaintEvent* event) int w = bound_rect.width(); int h = bound_rect.height(); - QColor bar_color = kGrayProcessColor; + QColor bar_color = emphasize_ ? kEmphasizedBarColor : kGrayProcessColor; if (has_subscription_) { switch (subscription_status_) @@ -109,7 +111,8 @@ void RMVHeapOverviewMemoryBar::paintEvent(QPaintEvent* event) } else { - painter.setPen(Qt::white); + QColor pen_color = emphasize_ ? Qt::black : Qt::white; + painter.setPen(pen_color); painter.drawText(memory_rect, Qt::AlignCenter | Qt::AlignHCenter, rmv::string_util::LocalizedValueMemory(size_, false, false)); } } @@ -124,11 +127,13 @@ void RMVHeapOverviewMemoryBar::SetParameters(uint64_t size, uint64_t extra_size, uint64_t max_size, bool has_subscription, - RmtSegmentSubscriptionStatus subscription_status) + RmtSegmentSubscriptionStatus subscription_status, + bool emphasize) { size_ = size; extra_size_ = extra_size; max_size_ = max_size; has_subscription_ = has_subscription; subscription_status_ = subscription_status; + emphasize_ = emphasize; } diff --git a/source/frontend/views/custom_widgets/rmv_heap_overview_memory_bar.h b/source/frontend/views/custom_widgets/rmv_heap_overview_memory_bar.h index 944ec16..ccefa8a 100644 --- a/source/frontend/views/custom_widgets/rmv_heap_overview_memory_bar.h +++ b/source/frontend/views/custom_widgets/rmv_heap_overview_memory_bar.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a heap overview memory bar. @@ -50,7 +50,13 @@ class RMVHeapOverviewMemoryBar : public QWidget /// @param [in] has_subscription Does this bar need to take into account memory subscription? /// If so it will be colored based on its subscription status, otherwise it will be gray. /// @param [in] subscription_status The current subscription status showing if the memory is oversubscribed or not. - void SetParameters(uint64_t size, uint64_t extra_size, uint64_t max_size, bool has_subscription, RmtSegmentSubscriptionStatus subscription_status); + /// @param [in] emphasize If true, the bar is highlighted with a lighter color. + void SetParameters(uint64_t size, + uint64_t extra_size, + uint64_t max_size, + bool has_subscription, + RmtSegmentSubscriptionStatus subscription_status, + bool emphasize); protected: /// @brief Implementation of Qt's paint event. @@ -69,6 +75,7 @@ class RMVHeapOverviewMemoryBar : public QWidget uint64_t max_size_; ///< Max size of bar. Used to scale all bars. bool has_subscription_; ///< Does this bar need subscription coloring. RmtSegmentSubscriptionStatus subscription_status_; ///< Subscription(none, over, under, near). Will determine bar color. + bool emphasize_; ///< If true, the bar is highlighted with a lighter color. }; #endif // RMV_VIEWS_CUSTOM_WIDGETS_RMV_HEAP_OVERVIEW_MEMORY_BAR_H_ diff --git a/source/frontend/views/custom_widgets/rmv_range_slider.cpp b/source/frontend/views/custom_widgets/rmv_range_slider.cpp new file mode 100644 index 0000000..09a5318 --- /dev/null +++ b/source/frontend/views/custom_widgets/rmv_range_slider.cpp @@ -0,0 +1,63 @@ +//============================================================================= +// Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. +/// @author AMD Developer Tools Team +/// @file +/// @brief Implementation of the custom range slider widget. +//============================================================================= + +#include "views/custom_widgets/rmv_range_slider.h" +#include "rmt_constants.h" +#include "util/rmv_util.h" +#include "util/string_util.h" + +#include +#include + +RmvRangeSlider::RmvRangeSlider(QWidget* parent) + : DoubleSliderWidget(parent) + , range_value_label_(nullptr) +{ +} + +RmvRangeSlider::~RmvRangeSlider() +{ +} + +void RmvRangeSlider::Init() +{ + DoubleSliderWidget::Init(); + + // Create a container with a layout for the slider and value label. + // Replace the slider on the UI with this container. + QWidget* container = new QWidget(parentWidget()); + container->setObjectName("rmv_range_slider_container_"); + container->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + QHBoxLayout* layout = new QHBoxLayout(container); + layout->setObjectName("rmv_range_slider_layout_"); + range_value_label_ = new RmvFixedWidthLabel(container); + range_value_label_->setObjectName("range_value_label_"); + + // Build a formatted string with the maximum expected width. + // The label will reserve this much horizontal space in the layout so that the slider to the left isn't affected when the value string changes length. + QString widest_range_string = + rmv::string_util::LocalizedValueMemory(999, false, false, false) + " - " + rmv::string_util::LocalizedValueMemory(999, false, false, false); + range_value_label_->SetWidestTextString(widest_range_string); + layout->addWidget(range_value_label_); + parentWidget()->layout()->replaceWidget(this, container); + layout->insertWidget(0, this); + + // Initialize the label range values to match the slider. + UpdateValues(LowerPosition(), UpperPosition()); + + connect(this, &DoubleSliderWidget::SpanChanged, this, &RmvRangeSlider::UpdateValues); +} + +void RmvRangeSlider::UpdateValues(const int min_value, const int max_value) +{ + if (range_value_label_ != nullptr) + { + const uint64_t lower_range = rmv_util::CalculateSizeThresholdFromStepValue(min_value, rmv::kSizeSliderRange - 1); + const uint64_t upper_range = rmv_util::CalculateSizeThresholdFromStepValue(max_value, rmv::kSizeSliderRange - 1); + range_value_label_->setText(rmv::string_util::GetMemoryRangeString(lower_range, upper_range)); + } +} diff --git a/source/frontend/views/custom_widgets/rmv_range_slider.h b/source/frontend/views/custom_widgets/rmv_range_slider.h new file mode 100644 index 0000000..a14eb16 --- /dev/null +++ b/source/frontend/views/custom_widgets/rmv_range_slider.h @@ -0,0 +1,41 @@ +//============================================================================= +// Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. +/// @author AMD Developer Tools Team +/// @file +/// @brief Header for the custom range slider widget. +//============================================================================= + +#ifndef RMV_VIEWS_CUSTOM_WIDGETS_RMV_RANGE_SLIDER_H_ +#define RMV_VIEWS_CUSTOM_WIDGETS_RMV_RANGE_SLIDER_H_ + +#include "qt_common/custom_widgets/double_slider_widget.h" + +#include "views/custom_widgets/rmv_fixed_width_label.h" +#include + +/// @brief Range slider that extends the double slider widget by adding a range value label. +class RmvRangeSlider : public DoubleSliderWidget +{ +public: + /// @brief Constructor + /// + /// @param [in] parent The parent of slider widget. + explicit RmvRangeSlider(QWidget* parent = nullptr); + + /// @brief Destructor. + virtual ~RmvRangeSlider(); + + /// @brief Intializes the range slider and adds the range value label. + void Init(); + +private slots: + /// @brief Slot to update the range value label when the slide is adjusted. + /// + /// @param [in] min_value The minimum index value for the slider. + /// @param [in] max_value The maximum index value for the slider. + void UpdateValues(const int min_value, const int max_value); + +private: + RmvFixedWidthLabel* range_value_label_; ///< A pointer to the label widget that displays the range values. +}; +#endif // RMV_VIEWS_CUSTOM_WIDGETS_RMV_RANGE_SLIDER_H_ diff --git a/source/frontend/views/custom_widgets/rmv_resource_details.cpp b/source/frontend/views/custom_widgets/rmv_resource_details.cpp index 60d378a..79a9cd7 100644 --- a/source/frontend/views/custom_widgets/rmv_resource_details.cpp +++ b/source/frontend/views/custom_widgets/rmv_resource_details.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the resource details widget. @@ -13,6 +13,7 @@ #include "qt_common/utils/scaling_manager.h" #include "rmt_print.h" +#include "util/rmv_util.h" #include "util/string_util.h" RMVResourceDetails::RMVResourceDetails(const RMVResourceDetailsConfig& config) @@ -63,11 +64,11 @@ void RMVResourceDetails::paint(QPainter* painter, const QStyleOptionGraphicsItem painter->drawText( 0, header_height, - "Resource ID " + QString::number(identifier) + " in allocation " + QString::number(static_cast(allocation->base_address))); + "Resource ID " + QString::number(identifier) + " in allocation " + rmv_util::GetVirtualAllocationName(allocation)); } else { - painter->drawText(0, header_height, "Unbound resource in allocation " + QString::number(static_cast(allocation->base_address))); + painter->drawText(0, header_height, "Unbound resource in allocation " + rmv_util::GetVirtualAllocationName(allocation)); } } else @@ -108,7 +109,7 @@ void RMVResourceDetails::paint(QPainter* painter, const QStyleOptionGraphicsItem x_pos += ScalingManager::Get().Scaled(100); painter->drawText(x_pos, header_height, "Offset"); - painter->drawText(x_pos, value_height, rmv::string_util::LocalizedValue(offset)); + painter->drawText(x_pos, value_height, rmv::string_util::LocalizedValueAddress(offset)); x_pos += ScalingManager::Get().Scaled(250); painter->drawText(x_pos, header_height, "Usage"); diff --git a/source/frontend/views/custom_widgets/rmv_resource_details.h b/source/frontend/views/custom_widgets/rmv_resource_details.h index 7212c91..177ab34 100644 --- a/source/frontend/views/custom_widgets/rmv_resource_details.h +++ b/source/frontend/views/custom_widgets/rmv_resource_details.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the resource details widget. diff --git a/source/frontend/views/custom_widgets/rmv_resource_timeline.cpp b/source/frontend/views/custom_widgets/rmv_resource_timeline.cpp index 6c12038..8e6a55a 100644 --- a/source/frontend/views/custom_widgets/rmv_resource_timeline.cpp +++ b/source/frontend/views/custom_widgets/rmv_resource_timeline.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a resource timeline widget. diff --git a/source/frontend/views/custom_widgets/rmv_resource_timeline.h b/source/frontend/views/custom_widgets/rmv_resource_timeline.h index 0076e98..9e3cd09 100644 --- a/source/frontend/views/custom_widgets/rmv_resource_timeline.h +++ b/source/frontend/views/custom_widgets/rmv_resource_timeline.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a resource timeline widget. diff --git a/source/frontend/views/custom_widgets/rmv_scaled_donut_widget.cpp b/source/frontend/views/custom_widgets/rmv_scaled_donut_widget.cpp index 9f6989d..2b7f4be 100644 --- a/source/frontend/views/custom_widgets/rmv_scaled_donut_widget.cpp +++ b/source/frontend/views/custom_widgets/rmv_scaled_donut_widget.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a donut widget. diff --git a/source/frontend/views/custom_widgets/rmv_scaled_donut_widget.h b/source/frontend/views/custom_widgets/rmv_scaled_donut_widget.h index 25d879a..3278b13 100644 --- a/source/frontend/views/custom_widgets/rmv_scaled_donut_widget.h +++ b/source/frontend/views/custom_widgets/rmv_scaled_donut_widget.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the donut widget. diff --git a/source/frontend/views/custom_widgets/rmv_snapshot_marker.cpp b/source/frontend/views/custom_widgets/rmv_snapshot_marker.cpp index 72e6768..e356058 100644 --- a/source/frontend/views/custom_widgets/rmv_snapshot_marker.cpp +++ b/source/frontend/views/custom_widgets/rmv_snapshot_marker.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a snapshot marker. diff --git a/source/frontend/views/custom_widgets/rmv_snapshot_marker.h b/source/frontend/views/custom_widgets/rmv_snapshot_marker.h index cc90ebb..3a04737 100644 --- a/source/frontend/views/custom_widgets/rmv_snapshot_marker.h +++ b/source/frontend/views/custom_widgets/rmv_snapshot_marker.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a snapshot marker. diff --git a/source/frontend/views/custom_widgets/rmv_snapshot_table_view.cpp b/source/frontend/views/custom_widgets/rmv_snapshot_table_view.cpp index 4ce8031..a6bb7f0 100644 --- a/source/frontend/views/custom_widgets/rmv_snapshot_table_view.cpp +++ b/source/frontend/views/custom_widgets/rmv_snapshot_table_view.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the snapshot table view. diff --git a/source/frontend/views/custom_widgets/rmv_snapshot_table_view.h b/source/frontend/views/custom_widgets/rmv_snapshot_table_view.h index 5f74aa1..22cbe6b 100644 --- a/source/frontend/views/custom_widgets/rmv_snapshot_table_view.h +++ b/source/frontend/views/custom_widgets/rmv_snapshot_table_view.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the snapshot table view. diff --git a/source/frontend/views/custom_widgets/rmv_snapshot_timeline.cpp b/source/frontend/views/custom_widgets/rmv_snapshot_timeline.cpp index 76065ba..99c93e5 100644 --- a/source/frontend/views/custom_widgets/rmv_snapshot_timeline.cpp +++ b/source/frontend/views/custom_widgets/rmv_snapshot_timeline.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the snapshot timeline visualization. @@ -33,7 +33,14 @@ RMVSnapshotTimeline::~RMVSnapshotTimeline() void RMVSnapshotTimeline::mousePressEvent(QMouseEvent* event) { - TimelineView::mousePressEvent(event); + if (this->dragMode() == QGraphicsView::NoDrag) + { + TimelineView::mousePressEvent(event); + } + else + { + QGraphicsView::mousePressEvent(event); + } emit UpdateSelectedDuration(selected_end_clock_ - selected_start_clock_); emit UpdateHoverClock(last_hovered_clock_); diff --git a/source/frontend/views/custom_widgets/rmv_snapshot_timeline.h b/source/frontend/views/custom_widgets/rmv_snapshot_timeline.h index ba273ae..7ac31ed 100644 --- a/source/frontend/views/custom_widgets/rmv_snapshot_timeline.h +++ b/source/frontend/views/custom_widgets/rmv_snapshot_timeline.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the snapshot timeline visualization. diff --git a/source/frontend/views/custom_widgets/rmv_timeline_graph.cpp b/source/frontend/views/custom_widgets/rmv_timeline_graph.cpp index 8ec4c35..f6eaa76 100644 --- a/source/frontend/views/custom_widgets/rmv_timeline_graph.cpp +++ b/source/frontend/views/custom_widgets/rmv_timeline_graph.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a widget that shows how memory usage changes per @@ -33,48 +33,53 @@ void RMVTimelineGraph::paint(QPainter* painter, const QStyleOptionGraphicsItem* Q_UNUSED(option); Q_UNUSED(widget); - painter->save(); - - qreal scaled_height = ScaledHeight(); - int num_buckets = config_.model_data->GetNumBuckets(); - - // For each bucket, ask the model for a rectangle to draw. - int bucket_index = 0; - bool success = true; - do + Q_ASSERT(config_.model_data != nullptr); + if (!config_.model_data->IsTimelineGenerationInProgress()) { - for (int bucket_group_index = 0; bucket_group_index < config_.model_data->GetNumBucketGroups(); bucket_group_index++) - { - QColor color = config_.colorizer->GetColor(bucket_group_index); - qreal y_pos = 0.0f; - qreal height = 0.0f; - success = config_.model_data->GetHistogramData(bucket_group_index, bucket_index, config_.model_data->GetNumBucketGroups(), y_pos, height); - if (success) - { - QRectF rect; + painter->save(); - // Flip the y-coord so (0, 0) is at the bottom left and scale values up to fit the view. - rect.setY(scaled_height - (y_pos * scaled_height)); - rect.setHeight(height * scaled_height); + qreal scaled_height = ScaledHeight(); + int num_buckets = config_.model_data->GetNumBuckets(); - // Calculate the x offset and width based on the bucket number and number of buckets. - qreal w = (qreal)ScaledWidth() / (qreal)num_buckets; - rect.setX(w * (qreal)bucket_index); - - // Allow for rounding error on width since coords are floating point. - rect.setWidth(w + 0.5); - - painter->fillRect(rect, color); - } - else + // For each bucket, ask the model for a rectangle to draw. + int bucket_index = 0; + bool success = true; + do + { + for (int bucket_group_number = 0; bucket_group_number < config_.model_data->GetNumBucketGroups(); bucket_group_number++) { - break; + int bucket_group_index = config_.model_data->RemapBucketGroupNumberToIndex(bucket_group_number); + QColor color = config_.colorizer->GetColor(bucket_group_index); + qreal y_pos = 0.0f; + qreal height = 0.0f; + success = config_.model_data->GetHistogramData(bucket_group_number, bucket_index, config_.model_data->GetNumBucketGroups(), y_pos, height); + if (success) + { + QRectF rect; + + // Flip the y-coord so (0, 0) is at the bottom left and scale values up to fit the view. + rect.setY(scaled_height - (y_pos * scaled_height)); + rect.setHeight(height * scaled_height); + + // Calculate the x offset and width based on the bucket number and number of buckets. + qreal w = (qreal)ScaledWidth() / (qreal)num_buckets; + rect.setX(w * (qreal)bucket_index); + + // Allow for rounding error on width since coords are floating point. + rect.setWidth(w + 0.5); + + painter->fillRect(rect, color); + } + else + { + break; + } } - } - bucket_index++; - } while (success); + bucket_index++; + } while (success); - painter->restore(); + painter->restore(); + } } void RMVTimelineGraph::UpdateDimensions(int width, int height) diff --git a/source/frontend/views/custom_widgets/rmv_timeline_graph.h b/source/frontend/views/custom_widgets/rmv_timeline_graph.h index a5af7ea..e78176a 100644 --- a/source/frontend/views/custom_widgets/rmv_timeline_graph.h +++ b/source/frontend/views/custom_widgets/rmv_timeline_graph.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a widget that shows how memory usage changes per diff --git a/source/frontend/views/custom_widgets/rmv_tooltip.cpp b/source/frontend/views/custom_widgets/rmv_tooltip.cpp index 0570c2e..4aad763 100644 --- a/source/frontend/views/custom_widgets/rmv_tooltip.cpp +++ b/source/frontend/views/custom_widgets/rmv_tooltip.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the custom tooltips. diff --git a/source/frontend/views/custom_widgets/rmv_tooltip.h b/source/frontend/views/custom_widgets/rmv_tooltip.h index ba0d711..d553af5 100644 --- a/source/frontend/views/custom_widgets/rmv_tooltip.h +++ b/source/frontend/views/custom_widgets/rmv_tooltip.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the custom tooltips. diff --git a/source/frontend/views/custom_widgets/rmv_tree_map_blocks.cpp b/source/frontend/views/custom_widgets/rmv_tree_map_blocks.cpp index b1444ca..a5e73c0 100644 --- a/source/frontend/views/custom_widgets/rmv_tree_map_blocks.cpp +++ b/source/frontend/views/custom_widgets/rmv_tree_map_blocks.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a tree map block collection. diff --git a/source/frontend/views/custom_widgets/rmv_tree_map_blocks.h b/source/frontend/views/custom_widgets/rmv_tree_map_blocks.h index 332b741..82d9c25 100644 --- a/source/frontend/views/custom_widgets/rmv_tree_map_blocks.h +++ b/source/frontend/views/custom_widgets/rmv_tree_map_blocks.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a tree map block collection. diff --git a/source/frontend/views/custom_widgets/rmv_tree_map_view.cpp b/source/frontend/views/custom_widgets/rmv_tree_map_view.cpp index 5604e11..ee37586 100644 --- a/source/frontend/views/custom_widgets/rmv_tree_map_view.cpp +++ b/source/frontend/views/custom_widgets/rmv_tree_map_view.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a tree map view. diff --git a/source/frontend/views/custom_widgets/rmv_tree_map_view.h b/source/frontend/views/custom_widgets/rmv_tree_map_view.h index 8ff8433..2e7676c 100644 --- a/source/frontend/views/custom_widgets/rmv_tree_map_view.h +++ b/source/frontend/views/custom_widgets/rmv_tree_map_view.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a tree map view. diff --git a/source/frontend/views/custom_widgets/themes_and_colors_item_button.cpp b/source/frontend/views/custom_widgets/themes_and_colors_item_button.cpp index 28452f3..eea9e00 100644 --- a/source/frontend/views/custom_widgets/themes_and_colors_item_button.cpp +++ b/source/frontend/views/custom_widgets/themes_and_colors_item_button.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a helper class for custom button rendering for diff --git a/source/frontend/views/custom_widgets/themes_and_colors_item_button.h b/source/frontend/views/custom_widgets/themes_and_colors_item_button.h index fccf3a2..b965d1a 100644 --- a/source/frontend/views/custom_widgets/themes_and_colors_item_button.h +++ b/source/frontend/views/custom_widgets/themes_and_colors_item_button.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a helper class for custom button rendering for the diff --git a/source/frontend/views/debug_window.cpp b/source/frontend/views/debug_window.cpp index c3444a2..8265b07 100644 --- a/source/frontend/views/debug_window.cpp +++ b/source/frontend/views/debug_window.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the debug window. diff --git a/source/frontend/views/debug_window.h b/source/frontend/views/debug_window.h index e293962..5028224 100644 --- a/source/frontend/views/debug_window.h +++ b/source/frontend/views/debug_window.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the debug window. diff --git a/source/frontend/views/delegates/rmv_compare_id_delegate.cpp b/source/frontend/views/delegates/rmv_compare_id_delegate.cpp index 0c43392..5ad2d5b 100644 --- a/source/frontend/views/delegates/rmv_compare_id_delegate.cpp +++ b/source/frontend/views/delegates/rmv_compare_id_delegate.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of RMVCompareIdDelegate. diff --git a/source/frontend/views/delegates/rmv_compare_id_delegate.h b/source/frontend/views/delegates/rmv_compare_id_delegate.h index 6ac2a57..c82032b 100644 --- a/source/frontend/views/delegates/rmv_compare_id_delegate.h +++ b/source/frontend/views/delegates/rmv_compare_id_delegate.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the custom colored circle with checkmark. diff --git a/source/frontend/views/delegates/rmv_regular_expression_validator.cpp b/source/frontend/views/delegates/rmv_regular_expression_validator.cpp index f70bb64..5287c4a 100644 --- a/source/frontend/views/delegates/rmv_regular_expression_validator.cpp +++ b/source/frontend/views/delegates/rmv_regular_expression_validator.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the regular expression validator with tooltip support. diff --git a/source/frontend/views/delegates/rmv_regular_expression_validator.h b/source/frontend/views/delegates/rmv_regular_expression_validator.h index 5bb1c8b..00268d7 100644 --- a/source/frontend/views/delegates/rmv_regular_expression_validator.h +++ b/source/frontend/views/delegates/rmv_regular_expression_validator.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the regular expression validator with tooltip support. diff --git a/source/frontend/views/delegates/rmv_resource_event_delegate.cpp b/source/frontend/views/delegates/rmv_resource_event_delegate.cpp index 0a84e1c..7959e9d 100644 --- a/source/frontend/views/delegates/rmv_resource_event_delegate.cpp +++ b/source/frontend/views/delegates/rmv_resource_event_delegate.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the resource event delegate. diff --git a/source/frontend/views/delegates/rmv_resource_event_delegate.h b/source/frontend/views/delegates/rmv_resource_event_delegate.h index eb9640f..33d918e 100644 --- a/source/frontend/views/delegates/rmv_resource_event_delegate.h +++ b/source/frontend/views/delegates/rmv_resource_event_delegate.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the resource event delegate. diff --git a/source/frontend/views/delegates/rmv_snapshot_name_delegate.cpp b/source/frontend/views/delegates/rmv_snapshot_name_delegate.cpp index 6ead78a..25ea1fc 100644 --- a/source/frontend/views/delegates/rmv_snapshot_name_delegate.cpp +++ b/source/frontend/views/delegates/rmv_snapshot_name_delegate.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the name delegate for the snapshot table. diff --git a/source/frontend/views/delegates/rmv_snapshot_name_delegate.h b/source/frontend/views/delegates/rmv_snapshot_name_delegate.h index 09d98f4..42b36c6 100644 --- a/source/frontend/views/delegates/rmv_snapshot_name_delegate.h +++ b/source/frontend/views/delegates/rmv_snapshot_name_delegate.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header of the name delegate for the snapshot table. diff --git a/source/frontend/views/keyboard_zoom_shortcuts.cpp b/source/frontend/views/keyboard_zoom_shortcuts.cpp index 5be7d2b..a26b396 100644 --- a/source/frontend/views/keyboard_zoom_shortcuts.cpp +++ b/source/frontend/views/keyboard_zoom_shortcuts.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the global keyboard shortcuts class. diff --git a/source/frontend/views/keyboard_zoom_shortcuts.h b/source/frontend/views/keyboard_zoom_shortcuts.h index dfc1536..f0b7237 100644 --- a/source/frontend/views/keyboard_zoom_shortcuts.h +++ b/source/frontend/views/keyboard_zoom_shortcuts.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the keyboard zoom shortcuts. diff --git a/source/frontend/views/main_window.cpp b/source/frontend/views/main_window.cpp index 6070c87..26286a8 100644 --- a/source/frontend/views/main_window.cpp +++ b/source/frontend/views/main_window.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the main window. @@ -112,7 +112,7 @@ MainWindow::MainWindow(QWidget* parent) SetupTabBar(); CreateActions(); CreateMenus(); - rmv::LoadAnimationManager::Get().Initialize(ui_->main_tab_widget_, file_menu_); + rmv::LoadAnimationManager::Get().Initialize(ui_->main_tab_widget_); ResetUI(); @@ -152,6 +152,7 @@ MainWindow::MainWindow(QWidget* parent) connect(&rmv::TraceManager::Get(), &rmv::TraceManager::TraceOpened, this, &MainWindow::OpenTrace); connect(&rmv::TraceManager::Get(), &rmv::TraceManager::TraceClosed, this, &MainWindow::CloseTrace); + connect(&rmv::TraceManager::Get(), &rmv::TraceManager::TraceOpenFailed, this, &MainWindow::SetupRecentTracesMenu); connect(&rmv::SnapshotManager::Get(), &rmv::SnapshotManager::SnapshotOpened, this, &MainWindow::OpenSnapshotPane); connect(&rmv::SnapshotManager::Get(), &rmv::SnapshotManager::CompareSnapshotsOpened, this, &MainWindow::OpenComparePane); @@ -163,6 +164,9 @@ MainWindow::MainWindow(QWidget* parent) connect(&rmv::MessageManager::Get(), &rmv::MessageManager::ChangeActionsRequested, this, &MainWindow::EnableActions); + ui_->save_testkit_json_->hide(); + ui_->top_spacer_label_->hide(); + // Connect to ScalingManager for notifications. connect(&ScalingManager::Get(), &ScalingManager::ScaleFactorChanged, this, &MainWindow::OnScaleFactorChanged); } @@ -359,6 +363,7 @@ void MainWindow::CreateActions() void MainWindow::EnableActions(const bool enable) { + close_trace_action_->setEnabled(enable); for (auto* action : actions()) { action->setEnabled(enable); @@ -414,9 +419,9 @@ void MainWindow::CreateMenus() file_menu_->addSeparator(); file_menu_->addAction(exit_action_); - file_menu_ = menuBar()->addMenu(tr("Help")); - file_menu_->addAction(help_action_); - file_menu_->addAction(about_action_); + help_menu_ = menuBar()->addMenu(tr("Help")); + help_menu_->addAction(help_action_); + help_menu_->addAction(about_action_); SetupRecentTracesMenu(); } diff --git a/source/frontend/views/main_window.h b/source/frontend/views/main_window.h index 8f4abbf..e70a996 100644 --- a/source/frontend/views/main_window.h +++ b/source/frontend/views/main_window.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the main window. diff --git a/source/frontend/views/main_window.ui b/source/frontend/views/main_window.ui index 3ccc00d..f3772b0 100644 --- a/source/frontend/views/main_window.ui +++ b/source/frontend/views/main_window.ui @@ -229,6 +229,40 @@
+ + + + + 0 + 0 + + + + + 10 + + + + Save testkit JSON + + + + + + + + 0 + 0 + + + + + + + 5 + + + diff --git a/source/frontend/views/settings/keyboard_shortcuts_pane.cpp b/source/frontend/views/settings/keyboard_shortcuts_pane.cpp index e06975b..0d2b505 100644 --- a/source/frontend/views/settings/keyboard_shortcuts_pane.cpp +++ b/source/frontend/views/settings/keyboard_shortcuts_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of Keyboard Shortcuts pane. diff --git a/source/frontend/views/settings/keyboard_shortcuts_pane.h b/source/frontend/views/settings/keyboard_shortcuts_pane.h index b64be24..6a776eb 100644 --- a/source/frontend/views/settings/keyboard_shortcuts_pane.h +++ b/source/frontend/views/settings/keyboard_shortcuts_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Keyboard Shortcuts pane. diff --git a/source/frontend/views/settings/settings_pane.cpp b/source/frontend/views/settings/settings_pane.cpp index 2905956..9a94188 100644 --- a/source/frontend/views/settings/settings_pane.cpp +++ b/source/frontend/views/settings/settings_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of Settings pane. diff --git a/source/frontend/views/settings/settings_pane.h b/source/frontend/views/settings/settings_pane.h index e526ef8..48f8030 100644 --- a/source/frontend/views/settings/settings_pane.h +++ b/source/frontend/views/settings/settings_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Settings pane. diff --git a/source/frontend/views/settings/themes_and_colors_pane.cpp b/source/frontend/views/settings/themes_and_colors_pane.cpp index ade19b0..a51df6b 100644 --- a/source/frontend/views/settings/themes_and_colors_pane.cpp +++ b/source/frontend/views/settings/themes_and_colors_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of Colors and Themes pane. @@ -34,10 +34,7 @@ ThemesAndColorsPane::ThemesAndColorsPane(QWidget* parent) button_group_.addButton(ui_->button_resource_depth_stencil_buffer_, kSettingThemesAndColorsResourceDsBuffer); button_group_.addButton(ui_->button_resource_render_target_, kSettingThemesAndColorsResourceRenderTarget); button_group_.addButton(ui_->button_resource_texture_, kSettingThemesAndColorsResourceTexture); - button_group_.addButton(ui_->button_resource_vertex_buffer_, kSettingThemesAndColorsResourceVertexBuffer); - button_group_.addButton(ui_->button_resource_index_buffer_, kSettingThemesAndColorsResourceIndexBuffer); button_group_.addButton(ui_->button_resource_ray_tracing_buffer_, kSettingThemesAndColorsResourceRayTracingBuffer); - button_group_.addButton(ui_->button_resource_uav_, kSettingThemesAndColorsResourceUav); button_group_.addButton(ui_->button_resource_shader_pipeline_, kSettingThemesAndColorsResourceShaderPipeline); button_group_.addButton(ui_->button_resource_command_buffer_, kSettingThemesAndColorsResourceCommandBuffer); button_group_.addButton(ui_->button_resource_heap_, kSettingThemesAndColorsResourceHeap); diff --git a/source/frontend/views/settings/themes_and_colors_pane.h b/source/frontend/views/settings/themes_and_colors_pane.h index ea9778f..a22e481 100644 --- a/source/frontend/views/settings/themes_and_colors_pane.h +++ b/source/frontend/views/settings/themes_and_colors_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Colors and Themes pane. diff --git a/source/frontend/views/settings/themes_and_colors_pane.ui b/source/frontend/views/settings/themes_and_colors_pane.ui index e565048..b14ee08 100644 --- a/source/frontend/views/settings/themes_and_colors_pane.ui +++ b/source/frontend/views/settings/themes_and_colors_pane.ui @@ -141,36 +141,6 @@ - - - - - 0 - 0 - - - - - 10 - 50 - false - true - - - - PointingHandCursor - - - - - - Event - - - true - - - @@ -271,8 +241,8 @@ - - + + 0 @@ -291,15 +261,15 @@ PointingHandCursor - Free space + Residency true - - + + 0 @@ -318,15 +288,15 @@ PointingHandCursor - Residency + No change true - - + + 0 @@ -345,15 +315,15 @@ PointingHandCursor - No change + Generated true - - + + 0 @@ -371,19 +341,16 @@ PointingHandCursor - - - - Command buffer + Increase true - - + + 0 @@ -402,15 +369,15 @@ PointingHandCursor - Internal + Cpu Mapping true - - + + 0 @@ -429,15 +396,15 @@ PointingHandCursor - Generated + Texture true - - + + 0 @@ -455,19 +422,16 @@ PointingHandCursor - - - - Shader pipeline + Page table true - - + + 0 @@ -476,28 +440,19 @@ - 10 - 50 - false - true + 75 + true + false + PreferAntialias - - PointingHandCursor - - - - - Vertex buffer - - - true + Snapshots - - + + 0 @@ -516,15 +471,15 @@ PointingHandCursor - Increase + Yes true - - + + 0 @@ -543,15 +498,15 @@ PointingHandCursor - Cpu Mapping + Live true - - + + 0 @@ -570,15 +525,15 @@ PointingHandCursor - Texture + Yes true - - + + 0 @@ -597,15 +552,15 @@ PointingHandCursor - Page table + DS texture true - - + + 0 @@ -623,19 +578,16 @@ PointingHandCursor - - - - Heap + Local true - - + + 0 @@ -646,17 +598,15 @@ 75 true - false - PreferAntialias - Snapshots + Resources - - + + 0 @@ -675,15 +625,15 @@ PointingHandCursor - Yes + Invisible true - - + + 0 @@ -702,15 +652,15 @@ PointingHandCursor - Live + VMA true - - + + 0 @@ -728,19 +678,16 @@ PointingHandCursor - - - - Index buffer + Decrease true - - + + 0 @@ -758,16 +705,19 @@ PointingHandCursor + + + - Yes + Acceleration structure true - - + + 0 @@ -776,25 +726,17 @@ - 10 - 50 - false - true + 75 + true - - PointingHandCursor - - DS buffer - - - true + Resource history - - + + 0 @@ -813,15 +755,15 @@ PointingHandCursor - Local + Compared true - - + + 0 @@ -835,12 +777,12 @@ - Resources + CPU mapped - - + + 0 @@ -859,15 +801,15 @@ PointingHandCursor - Invisible + No true - - + + 0 @@ -876,25 +818,17 @@ - 10 - 50 - false - true + 75 + true - - PointingHandCursor - - VMA - - - true + Heaps - - + + 0 @@ -913,15 +847,18 @@ PointingHandCursor - Decrease + Viewed true + + true + - - + + 0 @@ -939,19 +876,16 @@ PointingHandCursor - - - - Ray tracing + Host true - - + + 0 @@ -969,38 +903,16 @@ PointingHandCursor - - - - UAV + Unspecified true - - - - - 0 - 0 - - - - - 75 - true - - - - Resource history - - - - - + + 0 @@ -1019,15 +931,15 @@ PointingHandCursor - Compared + Highlight true - - + + 0 @@ -1036,17 +948,25 @@ - 75 - true + 10 + 50 + false + true + + PointingHandCursor + - CPU mapped + Render target + + + true - - + + 0 @@ -1072,8 +992,24 @@ - - + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + 0 @@ -1087,12 +1023,12 @@ - Heaps + Commit type - - + + 0 @@ -1111,18 +1047,15 @@ PointingHandCursor - Viewed + Committed true - - true - - - + + 0 @@ -1141,15 +1074,15 @@ PointingHandCursor - Host + Placed true - - + + 0 @@ -1168,15 +1101,15 @@ PointingHandCursor - Unspecified + Virtual true - - + + 0 @@ -1194,16 +1127,19 @@ PointingHandCursor + + + - Highlight + Command buffer true - - + + 0 @@ -1221,16 +1157,19 @@ PointingHandCursor + + + - Render target + Heap true - - + + 0 @@ -1252,15 +1191,15 @@ - Buffer + Shader pipeline true - - + + 0 @@ -1278,19 +1217,16 @@ PointingHandCursor - - - - Descriptors + Free space true - - + + 0 @@ -1309,50 +1245,15 @@ PointingHandCursor - No + Internal true - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Commit type - - - - - + + 0 @@ -1370,16 +1271,19 @@ PointingHandCursor + + + - Committed + Descriptors true - - + + 0 @@ -1397,16 +1301,19 @@ PointingHandCursor + + + - Placed + Buffer true - - + + 0 @@ -1424,8 +1331,11 @@ PointingHandCursor + + + - Virtual + Event true diff --git a/source/frontend/views/snapshot/allocation_explorer_pane.cpp b/source/frontend/views/snapshot/allocation_explorer_pane.cpp index 8601bc0..62a4db3 100644 --- a/source/frontend/views/snapshot/allocation_explorer_pane.cpp +++ b/source/frontend/views/snapshot/allocation_explorer_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Allocation Explorer pane. @@ -50,13 +50,17 @@ AllocationExplorerPane::AllocationExplorerPane(QWidget* parent) // Initialize allocation table. model_->InitializeAllocationTableModel(ui_->allocation_table_view_, 0, rmv::kVirtualAllocationColumnCount); ui_->allocation_table_view_->setCursor(Qt::PointingHandCursor); + ui_->allocation_table_view_->sortByColumn(rmv::kVirtualAllocationColumnAllocationSize, Qt::DescendingOrder); // Initialize resource table. model_->InitializeResourceTableModel(ui_->resource_table_view_, 0, rmv::kResourceColumnCount); ui_->resource_table_view_->setCursor(Qt::PointingHandCursor); + ui_->resource_table_view_->sortByColumn(rmv::kResourceColumnVirtualAddress, Qt::AscendingOrder); rmv::widget_util::InitCommonFilteringComponents(ui_->resource_search_box_, ui_->resource_size_slider_); rmv::widget_util::InitCommonFilteringComponents(ui_->allocation_search_box_, ui_->allocation_size_slider_); + rmv::widget_util::InitRangeSlider(ui_->resource_size_slider_); + rmv::widget_util::InitRangeSlider(ui_->allocation_size_slider_); ui_->aliased_resource_checkbox_->Initialize(false, rmv::kCheckboxEnableColor, Qt::black); colorizer_ = new rmv::Colorizer(); @@ -136,12 +140,9 @@ void AllocationExplorerPane::Refresh() // Prior to doing a table update, disable sorting since Qt is super slow about it. ui_->resource_table_view_->setSortingEnabled(false); - model_->BuildResourceSizeThresholds(); int32_t resource_count = model_->UpdateResourceTable(); - model_->ResourceSizeFilterChanged(ui_->resource_size_slider_->minimum(), ui_->resource_size_slider_->maximum()); - + ResourceSizeFilterChanged(ui_->resource_size_slider_->LowerValue(), ui_->resource_size_slider_->UpperValue()); ui_->resource_table_view_->setSortingEnabled(true); - ui_->resource_table_view_->sortByColumn(rmv::kResourceColumnMappedInvisible, Qt::DescendingOrder); ui_->resource_table_view_->horizontalHeader()->adjustSize(); ResizeItems(); @@ -169,11 +170,11 @@ void AllocationExplorerPane::Reset() model_->ResetModelValues(); ui_->allocation_size_slider_->SetLowerValue(0); - ui_->allocation_size_slider_->SetUpperValue(rmv::kSizeSliderRange); + ui_->allocation_size_slider_->SetUpperValue(ui_->allocation_size_slider_->maximum()); ui_->allocation_search_box_->setText(""); ui_->resource_size_slider_->SetLowerValue(0); - ui_->resource_size_slider_->SetUpperValue(rmv::kSizeSliderRange); + ui_->resource_size_slider_->SetUpperValue(ui_->resource_size_slider_->maximum()); ui_->resource_search_box_->setText(""); SelectResource(0); @@ -208,7 +209,6 @@ void AllocationExplorerPane::OpenSnapshot(RmtDataSnapshot* snapshot) ui_->allocation_table_view_->setSortingEnabled(false); model_->UpdateAllocationTable(); ui_->allocation_table_view_->setSortingEnabled(true); - ui_->allocation_table_view_->sortByColumn(rmv::kVirtualAllocationColumnAllocationSize, Qt::DescendingOrder); // Select it. ui_->allocation_table_view_->selectRow(0); diff --git a/source/frontend/views/snapshot/allocation_explorer_pane.h b/source/frontend/views/snapshot/allocation_explorer_pane.h index f4c3747..9a9055e 100644 --- a/source/frontend/views/snapshot/allocation_explorer_pane.h +++ b/source/frontend/views/snapshot/allocation_explorer_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Allocation Explorer pane. diff --git a/source/frontend/views/snapshot/allocation_explorer_pane.ui b/source/frontend/views/snapshot/allocation_explorer_pane.ui index 721e200..6fa2fa3 100644 --- a/source/frontend/views/snapshot/allocation_explorer_pane.ui +++ b/source/frontend/views/snapshot/allocation_explorer_pane.ui @@ -134,7 +134,7 @@ - + Qt::Horizontal @@ -444,7 +444,7 @@ - + Qt::Horizontal @@ -510,9 +510,9 @@
qt_common/custom_widgets/colored_legend_graphics_view.h
- DoubleSliderWidget + RmvRangeSlider QSlider -
qt_common/custom_widgets/double_slider_widget.h
+
views/custom_widgets/rmv_range_slider.h
ScaledLabel diff --git a/source/frontend/views/snapshot/allocation_overview_pane.cpp b/source/frontend/views/snapshot/allocation_overview_pane.cpp index c8af8b3..312d388 100644 --- a/source/frontend/views/snapshot/allocation_overview_pane.cpp +++ b/source/frontend/views/snapshot/allocation_overview_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the allocation overview pane. diff --git a/source/frontend/views/snapshot/allocation_overview_pane.h b/source/frontend/views/snapshot/allocation_overview_pane.h index 07b7ec6..52a15ed 100644 --- a/source/frontend/views/snapshot/allocation_overview_pane.h +++ b/source/frontend/views/snapshot/allocation_overview_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Allocation overview pane. diff --git a/source/frontend/views/snapshot/heap_overview_heap_layout.cpp b/source/frontend/views/snapshot/heap_overview_heap_layout.cpp index b15fe5b..4cad666 100644 --- a/source/frontend/views/snapshot/heap_overview_heap_layout.cpp +++ b/source/frontend/views/snapshot/heap_overview_heap_layout.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for a single heap in the heap overview pane. @@ -17,6 +17,9 @@ #include "util/string_util.h" #include "util/widget_util.h" +// A string used to describe the data presented by the resource usage donut. +static const QString kResourceDonutDescription = "Committed %1 memory\nGrouped by Resource usage"; + HeapOverviewHeapLayout::HeapOverviewHeapLayout(QWidget* parent) : QWidget(parent) , ui_(new Ui::HeapOverviewHeapLayout) @@ -66,9 +69,17 @@ void HeapOverviewHeapLayout::Initialize(RmtHeapType heap) model_->InitializeModel(ui_->content_cpu_visible_, rmv::kHeapOverviewCpuVisible, "text"); model_->InitializeModel(ui_->content_gpu_cached_, rmv::kHeapOverviewGpuCached, "text"); model_->InitializeModel(ui_->content_gpu_visible_, rmv::kHeapOverviewGpuVisible, "text"); + model_->InitializeModel(ui_->content_committed_, rmv::kHeapOverviewCommitted, "text"); + model_->InitializeModel(ui_->content_allocation_count_, rmv::kHeapOverviewAllocationCount, "text"); model_->InitializeModel(ui_->content_smallest_allocation_, rmv::kHeapOverviewSmallestAllocation, "text"); model_->InitializeModel(ui_->content_largest_allocation_, rmv::kHeapOverviewLargestAllocation, "text"); model_->InitializeModel(ui_->content_mean_allocation_, rmv::kHeapOverviewMeanAllocation, "text"); + model_->InitializeModel(ui_->content_resource_count_, rmv::kHeapOverviewResourceCount, "text"); + + ui_->label_resource_donut_description_->setText(kResourceDonutDescription.arg(RmtGetHeapTypeNameFromHeapType(heap))); + + ui_->content_committed_->hide(); + ui_->label_committed_->hide(); } int HeapOverviewHeapLayout::GetDonutSectionWidth() const @@ -190,16 +201,14 @@ void HeapOverviewHeapLayout::Update() } // Apply memory parameters to the memory bars. - ui_->bar_requested_->SetParameters(total_virtual_memory_requested, 0, max_size, true, subscription_status); - ui_->bar_bound_->SetParameters(total_bound_virtual_memory, 0, max_size, false, subscription_status); - ui_->bar_total_size_->SetParameters(total_physical_size, 0, max_size, false, subscription_status); - ui_->bar_committed_->SetParameters(total_physical_mapped_by_process, total_physical_mapped_by_other_processes, max_size, false, subscription_status); + ui_->bar_requested_->SetParameters(total_virtual_memory_requested, 0, max_size, true, subscription_status, false); + ui_->bar_bound_->SetParameters(total_bound_virtual_memory, 0, max_size, false, subscription_status, false); + ui_->bar_total_size_->SetParameters(total_physical_size, 0, max_size, false, subscription_status, true); // Update the various UI elements. ui_->bar_requested_->update(); ui_->bar_bound_->update(); ui_->bar_total_size_->update(); - ui_->bar_committed_->update(); ui_->donut_widget_->update(); } diff --git a/source/frontend/views/snapshot/heap_overview_heap_layout.h b/source/frontend/views/snapshot/heap_overview_heap_layout.h index d27a6a2..ff9906f 100644 --- a/source/frontend/views/snapshot/heap_overview_heap_layout.h +++ b/source/frontend/views/snapshot/heap_overview_heap_layout.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for a layout for a single heap in the heap overview pane. diff --git a/source/frontend/views/snapshot/heap_overview_heap_layout.ui b/source/frontend/views/snapshot/heap_overview_heap_layout.ui index 0ae13f1..f8cf0cf 100644 --- a/source/frontend/views/snapshot/heap_overview_heap_layout.ui +++ b/source/frontend/views/snapshot/heap_overview_heap_layout.ui @@ -195,27 +195,8 @@
- - - - - 0 - 0 - - - - - 0 - 20 - - - - The total size of the memory in this heap - - - - - + + 0 @@ -230,37 +211,18 @@ - The amount of memory in this heap requested by the application + The amount of memory in this heap that has bound resources - Requested + Bound Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - 0 - 0 - - - - - 0 - 20 - - - - The amount of memory in this heap requested by the application - - - - - + + 0 @@ -275,10 +237,10 @@ - The amount of memory in this heap that has bound resources + The amount of memory in this heap requested by the application - Bound + Requested Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -304,34 +266,27 @@ - - + + - + 0 0 - - - 8 - 75 - true - + + + 0 + 20 + - The amount of memory in this heap that has been committed to physical memory - - - Committed - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + The amount of memory in this heap requested by the application - - + + 0 @@ -345,7 +300,7 @@ - The amount of memory in this heap that has been committed to physical memory + The total size of the memory in this heap @@ -506,8 +461,8 @@ 10 - - + + 0 @@ -515,11 +470,63 @@ - Largest allocation: + mean - + + + + + 0 + 0 + + + + Resource count: + + + + + + + + 0 + 0 + + + + GPU Cached: + + + + + + + + 0 + 0 + + + + resource count + + + + + + + + 0 + 0 + + + + CPU Visible: + + + + @@ -532,8 +539,8 @@ - - + + 0 @@ -541,7 +548,7 @@ - GPU Visible: + smallest @@ -558,7 +565,7 @@ - + @@ -571,8 +578,8 @@ - - + + 0 @@ -580,12 +587,12 @@ - location + yes / no - - + + 0 @@ -593,12 +600,12 @@ - CPU Visible: + location - - + + 0 @@ -610,8 +617,8 @@ - - + + 0 @@ -619,7 +626,7 @@ - smallest + GPU Visible: @@ -636,8 +643,8 @@ - - + + 0 @@ -645,12 +652,12 @@ - GPU Cached: + Physical location of heap: - - + + 0 @@ -658,12 +665,12 @@ - yes / no + committed - - + + 0 @@ -671,12 +678,12 @@ - yes / no + Mean allocation: - - + + 0 @@ -684,12 +691,38 @@ - Physical location of heap: + Largest allocation: + + + + + + + + 0 + 0 + + + + Committed: + + + + + + + + 0 + 0 + + + + yes / no - + 0 @@ -697,12 +730,12 @@ - Mean allocation: + Allocation count: - + 0 @@ -710,7 +743,7 @@ - mean + allocation count @@ -790,6 +823,16 @@ + + + + Committed memory description + + + Qt::AlignCenter + + + @@ -933,17 +976,17 @@ QGraphicsView
qt_common/custom_widgets/colored_legend_graphics_view.h
+ + ScaledLabel + QLabel +
qt_common/custom_widgets/scaled_label.h
+
DonutPieWidget QWidget
qt_common/custom_widgets/donut_pie_widget.h
1
- - ScaledLabel - QLabel -
qt_common/custom_widgets/scaled_label.h
-
RMVHeapOverviewMemoryBar QWidget diff --git a/source/frontend/views/snapshot/heap_overview_pane.cpp b/source/frontend/views/snapshot/heap_overview_pane.cpp index 95c54bb..8d11242 100644 --- a/source/frontend/views/snapshot/heap_overview_pane.cpp +++ b/source/frontend/views/snapshot/heap_overview_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Heap Overview pane. diff --git a/source/frontend/views/snapshot/heap_overview_pane.h b/source/frontend/views/snapshot/heap_overview_pane.h index fce414b..d44bb80 100644 --- a/source/frontend/views/snapshot/heap_overview_pane.h +++ b/source/frontend/views/snapshot/heap_overview_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Heap Overview pane. diff --git a/source/frontend/views/snapshot/resource_details_pane.cpp b/source/frontend/views/snapshot/resource_details_pane.cpp index 9e99e43..ffc5dc8 100644 --- a/source/frontend/views/snapshot/resource_details_pane.cpp +++ b/source/frontend/views/snapshot/resource_details_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Resource details pane. @@ -227,7 +227,7 @@ void ResourceDetailsPane::Refresh() ui_->resource_timeline_table_view_->sortByColumn(rmv::kResourceHistoryColumnTime, Qt::AscendingOrder); rmv::widget_util::SetWidgetBackgroundColor(ui_->residency_donut_, Qt::white); - int value; + float value; QString name; QColor color; @@ -244,7 +244,7 @@ void ResourceDetailsPane::Refresh() value = 0; if (model_->GetResidencyData(resource_identifier_, heapTypes[i], value, name, color) == true) { - legends_scene_heaps_[i]->AddColorLegendItem(color, name + QString(" (%1%)").arg(value)); + legends_scene_heaps_[i]->AddColorLegendItem(color, name + " (" + QString::number(value, 'f', 2) + "%)"); ui_->residency_donut_->SetIndexValue(i, value); ui_->residency_donut_->SetIndexColor(i, color); } diff --git a/source/frontend/views/snapshot/resource_details_pane.h b/source/frontend/views/snapshot/resource_details_pane.h index f1f4fdc..a2d8b45 100644 --- a/source/frontend/views/snapshot/resource_details_pane.h +++ b/source/frontend/views/snapshot/resource_details_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Resource details pane. diff --git a/source/frontend/views/snapshot/resource_event_icons.cpp b/source/frontend/views/snapshot/resource_event_icons.cpp index 8c68900..d3e9130 100644 --- a/source/frontend/views/snapshot/resource_event_icons.cpp +++ b/source/frontend/views/snapshot/resource_event_icons.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the resource event icons. diff --git a/source/frontend/views/snapshot/resource_event_icons.h b/source/frontend/views/snapshot/resource_event_icons.h index d04ab11..a908579 100644 --- a/source/frontend/views/snapshot/resource_event_icons.h +++ b/source/frontend/views/snapshot/resource_event_icons.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the resource event icons. diff --git a/source/frontend/views/snapshot/resource_list_pane.cpp b/source/frontend/views/snapshot/resource_list_pane.cpp index 0eacc47..868ca70 100644 --- a/source/frontend/views/snapshot/resource_list_pane.cpp +++ b/source/frontend/views/snapshot/resource_list_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Resource List pane. @@ -21,6 +21,7 @@ #include "models/resource_item_model.h" #include "models/snapshot/resource_list_model.h" #include "settings/rmv_settings.h" +#include "util/string_util.h" ResourceListPane::ResourceListPane(QWidget* parent) : BasePane(parent) @@ -40,6 +41,7 @@ ResourceListPane::ResourceListPane(QWidget* parent) model_->InitializeTableModel(ui_->resource_table_view_, 0, rmv::kResourceColumnCount); ui_->resource_table_view_->setCursor(Qt::PointingHandCursor); + ui_->resource_table_view_->sortByColumn(rmv::kResourceColumnVirtualAddress, Qt::AscendingOrder); rmv::widget_util::InitMultiSelectComboBox(this, ui_->preferred_heap_combo_box_, rmv::text::kPreferredHeap); rmv::widget_util::InitMultiSelectComboBox(this, ui_->resource_usage_combo_box_, rmv::text::kResourceUsage); @@ -62,11 +64,13 @@ ResourceListPane::ResourceListPane(QWidget* parent) ui_->carousel_view_->setScene(carousel_->Scene()); rmv::widget_util::InitCommonFilteringComponents(ui_->search_box_, ui_->size_slider_); + rmv::widget_util::InitRangeSlider(ui_->size_slider_); connect(ui_->size_slider_, &DoubleSliderWidget::SpanChanged, this, &ResourceListPane::FilterBySizeSliderChanged); connect(ui_->search_box_, &QLineEdit::textChanged, this, &ResourceListPane::SearchBoxChanged); connect(ui_->resource_table_view_, &QTableView::clicked, this, &ResourceListPane::TableClicked); connect(ui_->resource_table_view_, &QTableView::doubleClicked, this, &ResourceListPane::TableDoubleClicked); + ui_->dump_resources_button_->hide(); // Set up a connection between the timeline being sorted and making sure the selected event is visible. connect(model_->GetResourceProxyModel(), &rmv::ResourceProxyModel::layoutChanged, this, &ResourceListPane::ScrollToSelectedResource); @@ -116,6 +120,7 @@ void ResourceListPane::Refresh() model_->UpdatePreferredHeapList(heap_filter_string); QString resource_filter_string = resource_usage_combo_box_model_->GetFilterString(ui_->resource_usage_combo_box_); model_->UpdateResourceUsageList(resource_filter_string); + FilterBySizeSliderChanged(ui_->size_slider_->LowerValue(), ui_->size_slider_->UpperValue()); } void ResourceListPane::OnTraceClose() @@ -131,7 +136,7 @@ void ResourceListPane::Reset() selected_resource_identifier_ = 0; ui_->size_slider_->SetLowerValue(0); - ui_->size_slider_->SetUpperValue(rmv::kSizeSliderRange); + ui_->size_slider_->SetUpperValue(ui_->size_slider_->maximum()); ui_->search_box_->setText(""); carousel_->ClearData(); @@ -188,7 +193,6 @@ void ResourceListPane::PopulateResourceTable() ui_->resource_table_view_->setSortingEnabled(false); model_->Update(); ui_->resource_table_view_->setSortingEnabled(true); - ui_->resource_table_view_->sortByColumn(rmv::kResourceColumnName, Qt::DescendingOrder); ui_->resource_table_view_->horizontalHeader()->adjustSize(); model_valid_ = true; SelectResourceInTable(); @@ -222,11 +226,12 @@ void ResourceListPane::HeapChanged(bool checked) SetMaximumResourceTableHeight(); } -void ResourceListPane::ResourceChanged(bool checked) +void ResourceListPane::ResourceChanged(bool checked, int changed_item_index) { - // Rebuild the table depending on what the state of the combo box items is. RMT_UNUSED(checked); + // Rebuild the table depending on what the state of the combo box items is. + resource_usage_combo_box_model_->UpdateCheckboxes(changed_item_index, ui_->resource_usage_combo_box_); QString filter_string = resource_usage_combo_box_model_->GetFilterString(ui_->resource_usage_combo_box_); model_->UpdateResourceUsageList(filter_string); SetMaximumResourceTableHeight(); diff --git a/source/frontend/views/snapshot/resource_list_pane.h b/source/frontend/views/snapshot/resource_list_pane.h index 7ca8910..b0a1734 100644 --- a/source/frontend/views/snapshot/resource_list_pane.h +++ b/source/frontend/views/snapshot/resource_list_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Resource List pane. @@ -74,8 +74,9 @@ private slots: /// @brief Handle what happens when a checkbox in the resource dropdown is checked or unchecked. /// - /// @param [in] checked Whether the checkbox is checked or unchecked. - void ResourceChanged(bool checked); + /// @param [in] checked Whether the checkbox is checked or unchecked. + /// @param [in] changed_item_index The index of the checkbox in the combo box that was changed. + void ResourceChanged(bool checked, int changed_item_index); /// @brief Resize child UI widgets when the DPI scale factor changes. void OnScaleFactorChanged(); diff --git a/source/frontend/views/snapshot/resource_list_pane.ui b/source/frontend/views/snapshot/resource_list_pane.ui index a39a18f..2f54d6c 100644 --- a/source/frontend/views/snapshot/resource_list_pane.ui +++ b/source/frontend/views/snapshot/resource_list_pane.ui @@ -126,7 +126,7 @@
- + Qt::Horizontal @@ -270,6 +270,19 @@ + + + + + 0 + 0 + + + + Dump resource table + + +
@@ -291,9 +304,9 @@ 1 - DoubleSliderWidget + RmvRangeSlider QSlider -
qt_common/custom_widgets/double_slider_widget.h
+
views/custom_widgets/rmv_range_slider.h
GraphicsView diff --git a/source/frontend/views/snapshot/resource_overview_pane.cpp b/source/frontend/views/snapshot/resource_overview_pane.cpp index 1d12ee9..2a3b22e 100644 --- a/source/frontend/views/snapshot/resource_overview_pane.cpp +++ b/source/frontend/views/snapshot/resource_overview_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the Resource Overview pane. @@ -23,6 +23,7 @@ #include "models/snapshot/resource_overview_model.h" #include "settings/rmv_settings.h" #include "util/widget_util.h" + #include "views/custom_widgets/rmv_colored_checkbox.h" ResourceOverviewPane::ResourceOverviewPane(QWidget* parent) @@ -68,7 +69,7 @@ ResourceOverviewPane::ResourceOverviewPane(QWidget* parent) connect(tree_map_models_.actual_heap_model, &rmv::HeapComboBoxModel::FilterChanged, this, &ResourceOverviewPane::ComboFiltersChanged); tree_map_models_.resource_usage_model->SetupResourceComboBox(ui_->resource_usage_combo_box_); - connect(tree_map_models_.resource_usage_model, &rmv::ResourceUsageComboBoxModel::FilterChanged, this, &ResourceOverviewPane::ComboFiltersChanged); + connect(tree_map_models_.resource_usage_model, &rmv::ResourceUsageComboBoxModel::FilterChanged, this, &ResourceOverviewPane::ResourceComboFiltersChanged); // Set up a list of required coloring modes, in order. // The list is terminated with kColorModeCount. @@ -145,7 +146,7 @@ ResourceOverviewPane::ResourceOverviewPane(QWidget* parent) ui_->resource_details_checkbox_->Initialize(true, rmv::kCheckboxEnableColor, Qt::black); - rmv::widget_util::InitDoubleSlider(ui_->size_slider_); + rmv::widget_util::InitRangeSlider(ui_->size_slider_); connect(ui_->size_slider_, &DoubleSliderWidget::SpanChanged, this, &ResourceOverviewPane::FilterBySizeSliderChanged); @@ -175,6 +176,7 @@ void ResourceOverviewPane::Refresh() { bool use_unbound = tree_map_models_.resource_usage_model->ItemInList(kRmtResourceUsageTypeFree); model_->Update(use_unbound); + FilterBySizeSliderChanged(ui_->size_slider_->LowerValue(), ui_->size_slider_->UpperValue()); } void ResourceOverviewPane::showEvent(QShowEvent* event) @@ -206,6 +208,9 @@ void ResourceOverviewPane::Reset() selected_resource_ = nullptr; resource_details_->UpdateResource(selected_resource_); + ui_->size_slider_->SetLowerValue(0); + ui_->size_slider_->SetUpperValue(ui_->size_slider_->maximum()); + ui_->slicing_button_one_->SetSelectedRow(GetRowForSliceType(RMVTreeMapBlocks::kSliceTypePreferredHeap)); ui_->slicing_button_two_->SetSelectedRow(GetRowForSliceType(RMVTreeMapBlocks::kSliceTypeVirtualAllocation)); ui_->slicing_button_three_->SetSelectedRow(GetRowForSliceType(RMVTreeMapBlocks::kSliceTypeResourceUsageType)); @@ -216,8 +221,6 @@ void ResourceOverviewPane::Reset() ui_->color_combo_box_->SetSelectedRow(0); colorizer_->ApplyColorMode(); - ui_->size_slider_->SetLowerValue(0); - ui_->size_slider_->SetUpperValue(rmv::kSizeSliderRange); UpdateDetailsTitle(); } @@ -291,6 +294,12 @@ void ResourceOverviewPane::ComboFiltersChanged(bool checked) ui_->tree_map_view_->UpdateTreeMap(); } +void ResourceOverviewPane::ResourceComboFiltersChanged(bool checked, int changed_item_index) +{ + tree_map_models_.resource_usage_model->UpdateCheckboxes(changed_item_index, ui_->resource_usage_combo_box_); + ComboFiltersChanged(checked); +} + void ResourceOverviewPane::UpdateSlicingLevel() { QVector slicingTypes; @@ -402,8 +411,7 @@ void ResourceOverviewPane::SelectUnboundResource(const RmtResource* unbound_reso void ResourceOverviewPane::FilterBySizeSliderChanged(int min_value, int max_value) { - bool use_unbound = tree_map_models_.resource_usage_model->ItemInList(kRmtResourceUsageTypeFree); - model_->FilterBySizeChanged(min_value, max_value, use_unbound); + model_->FilterBySizeChanged(min_value, max_value); ui_->tree_map_view_->UpdateTreeMap(); } diff --git a/source/frontend/views/snapshot/resource_overview_pane.h b/source/frontend/views/snapshot/resource_overview_pane.h index f31668a..9906418 100644 --- a/source/frontend/views/snapshot/resource_overview_pane.h +++ b/source/frontend/views/snapshot/resource_overview_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Resource Overview pane. @@ -92,6 +92,12 @@ private slots: /// @param [in] checked Whether the checkbox is checked or unchecked. void ComboFiltersChanged(bool checked); + /// @brief Handle what happens when a checkbox in the resource usage type filter dropdown is checked or unchecked. + /// + /// @param [in] checked Whether the checkbox is checked or unchecked. + /// @param [in] changed_item_index The index of the check box in the combo box that changed. + void ResourceComboFiltersChanged(bool checked, int changed_item_index); + /// @brief The slicing level changed. void SlicingLevelChanged(); diff --git a/source/frontend/views/snapshot/resource_overview_pane.ui b/source/frontend/views/snapshot/resource_overview_pane.ui index 0ab6f47..e972a73 100644 --- a/source/frontend/views/snapshot/resource_overview_pane.ui +++ b/source/frontend/views/snapshot/resource_overview_pane.ui @@ -398,7 +398,7 @@
- + 0 @@ -564,9 +564,9 @@
qt_common/custom_widgets/colored_legend_graphics_view.h
- DoubleSliderWidget + RmvRangeSlider QSlider -
qt_common/custom_widgets/double_slider_widget.h
+
views/custom_widgets/rmv_range_slider.h
ScaledLabel diff --git a/source/frontend/views/snapshot/snapshot_start_pane.cpp b/source/frontend/views/snapshot/snapshot_start_pane.cpp index 34f769f..4486790 100644 --- a/source/frontend/views/snapshot/snapshot_start_pane.cpp +++ b/source/frontend/views/snapshot/snapshot_start_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of Snapshot start pane. diff --git a/source/frontend/views/snapshot/snapshot_start_pane.h b/source/frontend/views/snapshot/snapshot_start_pane.h index 8252932..4199668 100644 --- a/source/frontend/views/snapshot/snapshot_start_pane.h +++ b/source/frontend/views/snapshot/snapshot_start_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Snapshot start pane. diff --git a/source/frontend/views/start/about_pane.cpp b/source/frontend/views/start/about_pane.cpp index 9db52c9..14cec45 100644 --- a/source/frontend/views/start/about_pane.cpp +++ b/source/frontend/views/start/about_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of RMV system information about pane. diff --git a/source/frontend/views/start/about_pane.h b/source/frontend/views/start/about_pane.h index a2f470c..a663d0c 100644 --- a/source/frontend/views/start/about_pane.h +++ b/source/frontend/views/start/about_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the system information about pane. diff --git a/source/frontend/views/start/recent_traces_pane.cpp b/source/frontend/views/start/recent_traces_pane.cpp index f0e96f3..1c2c407 100644 --- a/source/frontend/views/start/recent_traces_pane.cpp +++ b/source/frontend/views/start/recent_traces_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of Recent traces pane. diff --git a/source/frontend/views/start/recent_traces_pane.h b/source/frontend/views/start/recent_traces_pane.h index 15e0010..93766c8 100644 --- a/source/frontend/views/start/recent_traces_pane.h +++ b/source/frontend/views/start/recent_traces_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Recent traces pane. diff --git a/source/frontend/views/start/welcome_pane.cpp b/source/frontend/views/start/welcome_pane.cpp index 0fe1bda..0555e88 100644 --- a/source/frontend/views/start/welcome_pane.cpp +++ b/source/frontend/views/start/welcome_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the welcome pane. diff --git a/source/frontend/views/start/welcome_pane.h b/source/frontend/views/start/welcome_pane.h index 0a8063e..85a121d 100644 --- a/source/frontend/views/start/welcome_pane.h +++ b/source/frontend/views/start/welcome_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the welcome pane. diff --git a/source/frontend/views/timeline/device_configuration_pane.cpp b/source/frontend/views/timeline/device_configuration_pane.cpp index 483aeb5..bf5b44d 100644 --- a/source/frontend/views/timeline/device_configuration_pane.cpp +++ b/source/frontend/views/timeline/device_configuration_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the device configuration pane. diff --git a/source/frontend/views/timeline/device_configuration_pane.h b/source/frontend/views/timeline/device_configuration_pane.h index acf95b5..322fcb1 100644 --- a/source/frontend/views/timeline/device_configuration_pane.h +++ b/source/frontend/views/timeline/device_configuration_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the device configuration pane. diff --git a/source/frontend/views/timeline/keyboard_zoom_shortcuts_timeline.cpp b/source/frontend/views/timeline/keyboard_zoom_shortcuts_timeline.cpp index 52c2a33..5f3b0aa 100644 --- a/source/frontend/views/timeline/keyboard_zoom_shortcuts_timeline.cpp +++ b/source/frontend/views/timeline/keyboard_zoom_shortcuts_timeline.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation for the timeline keyboard shortcuts class. diff --git a/source/frontend/views/timeline/keyboard_zoom_shortcuts_timeline.h b/source/frontend/views/timeline/keyboard_zoom_shortcuts_timeline.h index a19f72e..29b3db7 100644 --- a/source/frontend/views/timeline/keyboard_zoom_shortcuts_timeline.h +++ b/source/frontend/views/timeline/keyboard_zoom_shortcuts_timeline.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the timeline keyboard zoom shortcuts. diff --git a/source/frontend/views/timeline/timeline_pane.cpp b/source/frontend/views/timeline/timeline_pane.cpp index 31d6f9f..95c75ec 100644 --- a/source/frontend/views/timeline/timeline_pane.cpp +++ b/source/frontend/views/timeline/timeline_pane.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of Timeline pane. @@ -34,6 +34,11 @@ const static QString kRenameAction = "Rename snapshot"; const static QString kDeleteAction = "Delete snapshot"; const static QString kCompareAction = "Compare snapshots"; +// Constants for building the selection duration and timeline hover position string. +const static QString kSelectionString = "Selection: "; +const static QString kDurationAndClockDivider = " | "; +const static QString kTimestampPadding = " "; // Extra padding to compensate for non-proportional font. + // The timeline type to revert to if calculating the resource usage size timeline type is cancelled. static int saved_timeline_type_index_ = 0; @@ -41,6 +46,8 @@ TimelinePane::TimelinePane(QWidget* parent) : BasePane(parent) , ui_(new Ui::TimelinePane) , thread_controller_(nullptr) + , hover_clock_(0) + , selection_duration_in_clocks_(0) { ui_->setupUi(this); @@ -95,9 +102,8 @@ TimelinePane::TimelinePane(QWidget* parent) // Set up a list of required timeline modes, in order. // The list is terminated with -1. - static const RmtDataTimelineType type_list[] = {kRmtDataTimelineTypeCommitted, + static const RmtDataTimelineType type_list[] = {kRmtDataTimelineTypeVirtualMemory, kRmtDataTimelineTypeResourceUsageCount, - kRmtDataTimelineTypeVirtualMemory, kRmtDataTimelineTypeResourceUsageVirtualSize, // kRmtDataTimelineTypeProcess, RmtDataTimelineType(-1)}; @@ -272,21 +278,35 @@ void TimelinePane::OnTraceClose() ui_->timeline_view_->Clear(); } -void TimelinePane::UpdateSelectedDuration(uint64_t duration) +void TimelinePane::UpdateClockAndSelectionLabel() { - QString text = "-"; + QString duration_and_clock_text = kSelectionString; - if (duration != 0) + if (selection_duration_in_clocks_ == 0) + { + duration_and_clock_text += "-"; + } + else { - text = rmv::time_util::ClockToTimeUnit(duration); + duration_and_clock_text += rmv::time_util::ClockToTimeUnit(selection_duration_in_clocks_); } - ui_->selection_clock_label_->setText(text); + duration_and_clock_text += kDurationAndClockDivider; + duration_and_clock_text += rmv::time_util::ClockToTimeUnit(hover_clock_); + + ui_->hover_clock_and_selection_label_->setText(duration_and_clock_text); +} + +void TimelinePane::UpdateSelectedDuration(uint64_t duration) +{ + selection_duration_in_clocks_ = duration; + UpdateClockAndSelectionLabel(); } void TimelinePane::UpdateHoverClock(uint64_t clock) { - ui_->hover_clock_label_->setText(rmv::time_util::ClockToTimeUnit(clock)); + hover_clock_ = clock; + UpdateClockAndSelectionLabel(); } void TimelinePane::Reset() @@ -307,6 +327,12 @@ void TimelinePane::SwitchTimeUnits() double ratio = rmv::time_util::TimeToClockRatio(); ui_->timeline_view_->UpdateTimeUnits(rmv::RMVSettings::Get().GetUnits(), ratio); model_->Update(); + + // Set the maximum length of the string used for the hover clock and selection label. + const QString max_timestamp_string = rmv::time_util::ClockToTimeUnit(model_->GetMaxTimestamp()); + const QString max_hover_clock_and_selection_string = + kTimestampPadding + kSelectionString + max_timestamp_string + kDurationAndClockDivider + max_timestamp_string; + ui_->hover_clock_and_selection_label_->SetWidestTextString(max_hover_clock_and_selection_string); } void TimelinePane::ChangeColoring() @@ -330,7 +356,8 @@ void TimelinePane::ZoomReset() zoom_icon_manager_->ZoomReset(); UpdateTimelineScrollbarContextMenu(false); - ui_->selection_clock_label_->setText("-"); + selection_duration_in_clocks_ = 0; + UpdateClockAndSelectionLabel(); ui_->timeline_view_->ZoomReset(); model_->UpdateMemoryGraph(ui_->timeline_view_->ViewableStartClk(), ui_->timeline_view_->ViewableEndClk()); diff --git a/source/frontend/views/timeline/timeline_pane.h b/source/frontend/views/timeline/timeline_pane.h index 9f292cc..06e77ca 100644 --- a/source/frontend/views/timeline/timeline_pane.h +++ b/source/frontend/views/timeline/timeline_pane.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Header for the Timeline pane. @@ -226,19 +226,24 @@ private slots: /// @param [in] shown Should the context menu be shown. void UpdateTimelineScrollbarContextMenu(bool shown); + /// @brief Update the label used to display the selection duration and mouse hover position on the timeline. + void UpdateClockAndSelectionLabel(); + /// @brief Helper function to set the maximum height of the table so it only contains rows with valid data. inline void SetMaximumSnapshotTableHeight() { ui_->snapshot_table_view_->setMaximumHeight(rmv::widget_util::GetTableHeight(ui_->snapshot_table_view_, model_->RowCount())); } - Ui::TimelinePane* ui_; ///< Pointer to the Qt UI design. - ZoomIconGroupManager* zoom_icon_manager_; ///< The object responsible for the zoom icon status. - rmv::TimelineModel* model_; ///< Container class for the widget models. - ColoredLegendScene* snapshot_legends_; ///< Snapshot legends above the timeline. - rmv::KeyboardZoomShortcutsTimeline* keyboard_zoom_shortcuts_; ///< Keyboard shortcut handler. - rmv::TimelineColorizer* colorizer_; ///< The colorizer used by the 'timeline type' combo box. - rmv::ThreadController* thread_controller_; ///< The thread for processing backend data. + Ui::TimelinePane* ui_; ///< Pointer to the Qt UI design. + ZoomIconGroupManager* zoom_icon_manager_; ///< The object responsible for the zoom icon status. + rmv::TimelineModel* model_; ///< Container class for the widget models. + ColoredLegendScene* snapshot_legends_; ///< Snapshot legends above the timeline. + rmv::KeyboardZoomShortcutsTimeline* keyboard_zoom_shortcuts_; ///< Keyboard shortcut handler. + rmv::TimelineColorizer* colorizer_; ///< The colorizer used by the 'timeline type' combo box. + rmv::ThreadController* thread_controller_; ///< The thread for processing backend data. + uint64_t hover_clock_; ///< The mouse position in clocks on the timeline. + uint64_t selection_duration_in_clocks_; ///< The duration of the timeline selection in clocks. }; #endif // RMV_VIEWS_TIMELINE_TIMELINE_PANE_H_ diff --git a/source/frontend/views/timeline/timeline_pane.ui b/source/frontend/views/timeline/timeline_pane.ui index 2fb09c7..bd22410 100644 --- a/source/frontend/views/timeline/timeline_pane.ui +++ b/source/frontend/views/timeline/timeline_pane.ui @@ -364,7 +364,7 @@ 0
- + 0 @@ -378,20 +378,7 @@ 0 - - - - 0 - 0 - - - - Selection: - - - - - + 0 @@ -401,25 +388,8 @@ - - - - - - - Qt::Vertical - - - - - - - - 0 - 0 - - - - - + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -435,7 +405,7 @@
- + 0 @@ -688,15 +658,15 @@ Qt::Vertical + + QSizePolicy::MinimumExpanding + 40 5 - - QSizePolicy::MinimumExpanding -
@@ -792,6 +762,11 @@ QLabel
qt_common/custom_widgets/scaled_label.h
+ + RmvFixedWidthLabel + QLabel +
views/custom_widgets/rmv_fixed_width_label.h
+
ScaledPushButton QPushButton @@ -802,16 +777,16 @@ QLineEdit
qt_common/custom_widgets/text_search_widget.h
- - RMVSnapshotTableView - ScaledTableView -
views/custom_widgets/rmv_snapshot_table_view.h
-
RMVSnapshotTimeline QGraphicsView
views/custom_widgets/rmv_snapshot_timeline.h
+ + RMVSnapshotTableView + QWidget +
views/custom_widgets/rmv_snapshot_table_view.h
+
diff --git a/source/parser/CMakeLists.txt b/source/parser/CMakeLists.txt index 93fd5fa..d6608d5 100644 --- a/source/parser/CMakeLists.txt +++ b/source/parser/CMakeLists.txt @@ -1,3 +1,8 @@ +####################################################################################################################### +### Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. +### \author AMD Developer Tools Team +####################################################################################################################### + cmake_minimum_required(VERSION 3.10) project(RmvParser) @@ -8,6 +13,7 @@ include_directories(AFTER ../parser) # List of all source files. It may be possible to have the build process call cmake to update the makefiles # only when this file has changed (ie source files have been added or removed) + set( SOURCES "rmt_address_helper.cpp" "rmt_address_helper.h" @@ -50,6 +56,7 @@ set( LINUX_SOURCES "linux/safe_crt.h" ) + # specify output library name IF(WIN32) add_library(${PROJECT_NAME} ${SOURCES}) @@ -69,3 +76,4 @@ endforeach() ENDIF(WIN32) devtools_target_options(${PROJECT_NAME}) + diff --git a/source/parser/linux/safe_crt.cpp b/source/parser/linux/safe_crt.cpp index a1dfc10..f90d645 100644 --- a/source/parser/linux/safe_crt.cpp +++ b/source/parser/linux/safe_crt.cpp @@ -1,5 +1,5 @@ //============================================================================== -// Copyright (c) 2016-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2016-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Linux implementation of Windows safe CRT functions. diff --git a/source/parser/linux/safe_crt.h b/source/parser/linux/safe_crt.h index 3f957df..c0b68ca 100644 --- a/source/parser/linux/safe_crt.h +++ b/source/parser/linux/safe_crt.h @@ -1,5 +1,5 @@ //============================================================================== -// Copyright (c) 2016-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2016-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Linux definition of Windows safe CRT functions. diff --git a/source/parser/rmt_address_helper.cpp b/source/parser/rmt_address_helper.cpp index a4f1a41..1e375f7 100644 --- a/source/parser/rmt_address_helper.cpp +++ b/source/parser/rmt_address_helper.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of helper functions for working with addresses. diff --git a/source/parser/rmt_address_helper.h b/source/parser/rmt_address_helper.h index 50d0c71..59b617d 100644 --- a/source/parser/rmt_address_helper.h +++ b/source/parser/rmt_address_helper.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Helpers for working with addresses. diff --git a/source/parser/rmt_assert.cpp b/source/parser/rmt_assert.cpp index 09902b7..9ee31d7 100644 --- a/source/parser/rmt_assert.cpp +++ b/source/parser/rmt_assert.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of assert. diff --git a/source/parser/rmt_assert.h b/source/parser/rmt_assert.h index 9bf914c..5181eda 100644 --- a/source/parser/rmt_assert.h +++ b/source/parser/rmt_assert.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of assert. diff --git a/source/parser/rmt_constants.h b/source/parser/rmt_constants.h index 336a0fa..7e60bf8 100644 --- a/source/parser/rmt_constants.h +++ b/source/parser/rmt_constants.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Intended to hold globally-known definitions. @@ -8,6 +8,8 @@ #ifndef RMV_PARSER_RMT_CONSTANTS_H_ #define RMV_PARSER_RMT_CONSTANTS_H_ +#include + #ifdef __cplusplus extern "C" { #endif // #ifdef __cplusplus @@ -15,6 +17,9 @@ extern "C" { // The file extensions for trace files. static const char* kRMVTraceFileExtension = ".rmv"; static const char* kRGDTraceFileExtension = ".rgd"; + +static const uint32_t kGfx10AsicFamily = 0x8F; + #ifdef __cplusplus } #endif // __cplusplus diff --git a/source/parser/rmt_error.h b/source/parser/rmt_error.h index bdf9f56..dc86934 100644 --- a/source/parser/rmt_error.h +++ b/source/parser/rmt_error.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Error codes. @@ -41,6 +41,7 @@ static const RmtErrorCode kRmtErrorResourceAlreadyBound = 0x80000012; /// A static const RmtErrorCode kRmtErrorFileAlreadyOpened = 0x80000013; /// The operation failed because a file was already opened. static const RmtErrorCode kRmtErrorFileAccessFailed = 0x80000014; /// The operation failed because a file couldn't be accessed. static const RmtErrorCode kRmtErrorPageTableSizeExceeded = 0x80000015; /// The operation failed because the page table size was exceeded. +static const RmtErrorCode kRmtErrorTraceFileNotSupported = 0x80000016; /// The operation failed because a trace file is unsupported. /// Helper macro to return error code y from a function when a specific condition, x, is not met. #define RMT_RETURN_ON_ERROR(x, y) \ diff --git a/source/parser/rmt_file_format.cpp b/source/parser/rmt_file_format.cpp index 072b043..b3c8a6b 100644 --- a/source/parser/rmt_file_format.cpp +++ b/source/parser/rmt_file_format.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of functions for working with the RMT file format. diff --git a/source/parser/rmt_file_format.h b/source/parser/rmt_file_format.h index 5d1aa86..e186279 100644 --- a/source/parser/rmt_file_format.h +++ b/source/parser/rmt_file_format.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of structures and functions for the RMT file format. diff --git a/source/parser/rmt_format.h b/source/parser/rmt_format.h index f60ce76..11e57a0 100644 --- a/source/parser/rmt_format.h +++ b/source/parser/rmt_format.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definitions of the RMT format. @@ -65,14 +65,15 @@ typedef enum RmtTokenType /// An enumeration of user data types. typedef enum RmtUserdataType { - kRmtUserdataTypeName = 0, ///< The user data contains a string which is relevant to the following sequence of tokens. - kRmtUserdataTypeSnapshot = 1, ///< The user data contains a string which names a specific momemnt in time. - kRmtUserdataTypeBinary = 2, ///< The user data contains a blind binary payload. - kRmtUserdataTypeReserved = 3, ///< Reserved for future expansion. - kRmtUserdataTypeCorrelation = 4, ///< The user data contains 2 32-bit handles for matching resource names to DX12 resources. - kRmtUserdataTypeMarkImplicitResource = 5, ///< The user data contains a 32-bit resource ID that should be filtered because it was created implicitly. - kRmtUserdataTypeName_V2 = 6, ///< The user data contains a string and a time delay. - kRmtUserdataTypeMarkImplicitResource_V2 = 7 ///< The user data contains a 32-bit implicit resource ID, with time delay. + kRmtUserdataTypeName = 0, ///< The user data contains a string which is relevant to the following sequence of tokens. + kRmtUserdataTypeSnapshot = 1, ///< The user data contains a string which names a specific momemnt in time. + kRmtUserdataTypeBinary = 2, ///< The user data contains a blind binary payload. + kRmtUserdataTypeReserved = 3, ///< Reserved for future expansion. + kRmtUserdataTypeCorrelation = 4, ///< The user data contains 2 32-bit handles for matching resource names to DX12 resources. + kRmtUserdataTypeMarkImplicitResource = 5, ///< The user data contains a 32-bit resource ID that should be filtered because it was created implicitly. + kRmtUserdataTypeName_V2 = 6, ///< The user data contains a string and a time delay. + kRmtUserdataTypeMarkImplicitResource_V2 = + 7 ///< The user data contains a 32-bit implicit resource ID, with time delay. RMT Spec version 1.9+ also contains implicit resource type. } RmtUserdataType; /// An enumeration of miscellaenous events. @@ -130,17 +131,16 @@ typedef enum RmtResourceType /// to insure they are placed in the correct order. typedef enum RmtResourceUsageType { - kRmtResourceUsageTypeUnknown, ///< The resource usage type is unknown. - kRmtResourceUsageTypeFree, ///< An additional type to represent memory that is allocated, but not bound to something. - kRmtResourceUsageTypeHeap, ///< The resource is a memory heap. - kRmtResourceUsageTypeBuffer, ///< The resource is a buffer. - kRmtResourceUsageTypeVertexBuffer, ///< The resource is a vertex buffer. - kRmtResourceUsageTypeIndexBuffer, ///< The resource is an index buffer. - kRmtResourceUsageTypeRayTracingBuffer, ///< The resource is a ray tracing-related buffer (ie BVH). - kRmtResourceUsageTypeUav, ///< The resource is an unordered access view. - kRmtResourceUsageTypeTexture, ///< The resource is a texture. - kRmtResourceUsageTypeRenderTarget, ///< The resource is a color target. - kRmtResourceUsageTypeDepthStencil, ///< The resource is a depth/stencil buffer. + kRmtResourceUsageTypeUnknown, ///< The resource usage type is unknown. + kRmtResourceUsageTypeFree, ///< An additional type to represent memory that is allocated, but not bound to something. + kRmtResourceUsageTypeHeap, ///< The resource is a memory heap. + kRmtResourceUsageTypeBuffer, ///< The resource is a buffer. + kRmtResourceUsageTypeVertexBuffer = kRmtResourceUsageTypeBuffer, ///< The resource is a vertex buffer (not used). + kRmtResourceUsageTypeIndexBuffer = kRmtResourceUsageTypeBuffer, ///< The resource is an index buffer (not used). + kRmtResourceUsageTypeRayTracingBuffer, ///< The resource is a ray tracing-related buffer (ie BVH). + kRmtResourceUsageTypeTexture, ///< The resource is a texture. + kRmtResourceUsageTypeRenderTarget, ///< The resource is a color target. + kRmtResourceUsageTypeDepthStencil, ///< The resource is a depth/stencil buffer. kRmtResourceUsageTypeInternal, kRmtResourceUsageTypeCommandBuffer, ///< The resource is a command buffer. kRmtResourceUsageTypeDescriptors, ///< The resource is a descriptor heap/pool. @@ -148,7 +148,8 @@ typedef enum RmtResourceUsageType kRmtResourceUsageTypeGpuEvent, ///< The resource is a GPU event. // Add above this. - kRmtResourceUsageTypeCount + kRmtResourceUsageTypeCount, + kRmtResourceUsageTypeAll = kRmtResourceUsageTypeCount ///< A value used to indicates all usage types are selected. } RmtResourceUsageType; /// An enumeration of process events. @@ -170,6 +171,24 @@ typedef enum RmtOwnerType kRmtOwnerTypeCount } RmtOwnerType; +/// An enumeration of the various heap types for a resource. +typedef enum RmtResourceHeapType +{ + kRmtResourceHeapTypeImmutable = 0, ///< Placed Resource (many placed resources can be immutably joined with a fully created heap). + kRmtResourceHeapTypeImplicitHeap = 1, ///< Committed Resource. + kRmtResourceHeapTypeResource = 2, ///< An API Heap. + kRmtResourceHeapTypeReserved = 3, ///< Page-mapped to one or more heaps, or nothing at all. + kRmtResourceHeapTypeImmutableResource = 4 ///< Placed texture on a reserved buffer which is page-mapped to one or more heaps, or nothing at all. +} RmtResourceHeapType; + +/// An enumeration of the implicit resource types. +typedef enum RmtImplicitResourceType +{ + kRmtImplicitResourceTypeUnused = 0, ///< The resource is not marked implicit. + kRmtImplicitResourceTypeImplicitHeap = 1, ///< The resource is marked as an implicit heap. + kRmtImplicitResourceTypeImplicitResource = 2, ///< The resource is marked as an implicit image or buffer. +} RmtImplicitResourceType; + /// An enumeraetion of the various commit types for a resource. typedef enum RmtCommitType { diff --git a/source/parser/rmt_parser.cpp b/source/parser/rmt_parser.cpp index 1606efe..8eb28e9 100644 --- a/source/parser/rmt_parser.cpp +++ b/source/parser/rmt_parser.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of functions for parsing RMT data. @@ -613,24 +613,50 @@ static RmtErrorCode ParseUserdata(RmtParser* rmt_parser, const uint16_t token_he const RmtResourceIdentifier resource_identifier = static_cast(resource_id_value); out_userdata_token->resource_identifier = resource_identifier; out_userdata_token->time_delay = 0; + out_userdata_token->implicit_resource_type = RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitResource; #ifdef _IMPLICIT_RESOURCE_LOGGING RmtPrint("ParseUserdata() - Store implicit resource ID: 0x%llx", out_userdata_token->resource_identifier); #endif // _IMPLICIT_RESOURCE_LOGGING } else if (out_userdata_token->userdata_type == kRmtUserdataTypeMarkImplicitResource_V2) { - typedef uint64_t NameTimeDelay; - - const uintptr_t resource_id_address = (reinterpret_cast(payload)); - const uint32_t resource_id_value = *(reinterpret_cast(resource_id_address)); - const RmtResourceIdentifier resource_identifier = static_cast(resource_id_value); - out_userdata_token->resource_identifier = resource_identifier; + // Parse the resource identifier from the payload. + typedef uint32_t DriverResourceIdentifier; + const uintptr_t resource_id_address = (reinterpret_cast(payload)); + const DriverResourceIdentifier resource_id_value = *(reinterpret_cast(resource_id_address)); + out_userdata_token->resource_identifier = static_cast(resource_id_value); + + // Parse the time delay from the payload. + typedef uint64_t TokenTimeDelay; + const uintptr_t time_delay_address = ((uintptr_t)payload) + sizeof(uint32_t); + const TokenTimeDelay time_delay_value = *((TokenTimeDelay*)time_delay_address); + out_userdata_token->time_delay = time_delay_value; + + // Set the default implicit resource type value. + out_userdata_token->implicit_resource_type = RmtImplicitResourceType::kRmtImplicitResourceTypeUnused; + + // Check to see if the MarkImplicitResource UserData token contains a HeapType property. + typedef uint8_t ResourceHeapType; + if (static_cast(out_userdata_token->size_in_bytes) >= (sizeof(DriverResourceIdentifier) + sizeof(TokenTimeDelay) + sizeof(ResourceHeapType))) + { + // Parse the implicit resource type from the payload if its present. + const uintptr_t resource_heap_type_address = (reinterpret_cast(payload) + sizeof(resource_id_value) + sizeof(time_delay_value)); + const uint8_t resource_heap_type_value = *(reinterpret_cast(resource_heap_type_address)); + if (resource_heap_type_value == RmtResourceHeapType::kRmtResourceHeapTypeImplicitHeap) + { + out_userdata_token->implicit_resource_type = RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitHeap; + } + else if (resource_heap_type_value == RmtResourceHeapType::kRmtResourceHeapTypeResource) + { + out_userdata_token->implicit_resource_type = RmtImplicitResourceType::kRmtImplicitResourceTypeImplicitResource; + } + } - const uintptr_t time_delay_address = ((uintptr_t)payload) + sizeof(uint32_t); - const NameTimeDelay time_delay_value = *((NameTimeDelay*)time_delay_address); - out_userdata_token->time_delay = time_delay_value; #ifdef _IMPLICIT_RESOURCE_LOGGING - RmtPrint("ParseUserdata() - Store implicit resource ID: 0x%llx", out_userdata_token->resource_identifier); + RmtPrint("ParseUserdata() - Store implicit resource ID: 0x%llx, time_delay = %ull, implicit_resource_type = %i", + out_userdata_token->resource_identifier, + out_userdata_token->time_delay, + out_userdata_token->implicit_resource_type); #endif // _IMPLICIT_RESOURCE_LOGGING } @@ -1568,8 +1594,7 @@ RmtErrorCode RmtParserAdvance(RmtParser* rmt_parser, RmtToken* out_token, RmtPar out_token->type = token_type; // Assert that if this is the first token in the stream (i.e. the offset is 0) that the token type is a timestamp. - RMT_ASSERT((rmt_parser->stream_current_offset > 0) || - ((rmt_parser->stream_current_offset == 0) && token_type == kRmtTokenTypeTimestamp)); + RMT_ASSERT((rmt_parser->stream_current_offset > 0) || ((rmt_parser->stream_current_offset == 0) && token_type == kRmtTokenTypeTimestamp)); switch (token_type) { diff --git a/source/parser/rmt_parser.h b/source/parser/rmt_parser.h index c1e9afd..950d3fd 100644 --- a/source/parser/rmt_parser.h +++ b/source/parser/rmt_parser.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Core parsing code for RMT data. diff --git a/source/parser/rmt_platform.cpp b/source/parser/rmt_platform.cpp index 3cbbad8..eeff8e7 100644 --- a/source/parser/rmt_platform.cpp +++ b/source/parser/rmt_platform.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of platform-specific utils. diff --git a/source/parser/rmt_platform.h b/source/parser/rmt_platform.h index 9b9e885..69fc5a8 100644 --- a/source/parser/rmt_platform.h +++ b/source/parser/rmt_platform.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Platform specific utilities. diff --git a/source/parser/rmt_print.cpp b/source/parser/rmt_print.cpp index 0eb0a54..c093be7 100644 --- a/source/parser/rmt_print.cpp +++ b/source/parser/rmt_print.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of printing helper functions for RMT. @@ -91,7 +91,7 @@ const char* RmtGetResourceUsageTypeNameFromResourceUsageType(const RmtResourceUs switch (usage_type) { case kRmtResourceUsageTypeDepthStencil: - return "Depth stencil buffer"; + return "Depth stencil texture"; case kRmtResourceUsageTypeRenderTarget: return "Render target"; @@ -99,17 +99,8 @@ const char* RmtGetResourceUsageTypeNameFromResourceUsageType(const RmtResourceUs case kRmtResourceUsageTypeTexture: return "Texture"; - case kRmtResourceUsageTypeVertexBuffer: - return "Vertex buffer"; - - case kRmtResourceUsageTypeIndexBuffer: - return "Index buffer"; - case kRmtResourceUsageTypeRayTracingBuffer: - return "Ray tracing"; - - case kRmtResourceUsageTypeUav: - return "UAV"; + return "Acceleration structure"; case kRmtResourceUsageTypeShaderPipeline: return "Shader pipeline"; @@ -124,7 +115,7 @@ const char* RmtGetResourceUsageTypeNameFromResourceUsageType(const RmtResourceUs return "Descriptors"; case kRmtResourceUsageTypeBuffer: - return "Multi-use buffer"; + return "Buffer"; case kRmtResourceUsageTypeFree: return "Unbound"; diff --git a/source/parser/rmt_print.h b/source/parser/rmt_print.h index 9237bc7..c685a49 100644 --- a/source/parser/rmt_print.h +++ b/source/parser/rmt_print.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// $brief Printing helper functions for RMT. diff --git a/source/parser/rmt_profile.h b/source/parser/rmt_profile.h index ffe3a8e..66256a1 100644 --- a/source/parser/rmt_profile.h +++ b/source/parser/rmt_profile.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Profile utils. diff --git a/source/parser/rmt_rdf_adapter_info.cpp b/source/parser/rmt_rdf_adapter_info.cpp index e39241a..c8c5769 100644 --- a/source/parser/rmt_rdf_adapter_info.cpp +++ b/source/parser/rmt_rdf_adapter_info.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the RFD Adapter Information chunk parser. diff --git a/source/parser/rmt_rdf_adapter_info.h b/source/parser/rmt_rdf_adapter_info.h index 7efdb4a..a139268 100644 --- a/source/parser/rmt_rdf_adapter_info.h +++ b/source/parser/rmt_rdf_adapter_info.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of the RFD Adapter Information chunk parser diff --git a/source/parser/rmt_rdf_data_stream.cpp b/source/parser/rmt_rdf_data_stream.cpp index 95690e0..a1dbd43 100644 --- a/source/parser/rmt_rdf_data_stream.cpp +++ b/source/parser/rmt_rdf_data_stream.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the RFD Data Stream chunk parser. diff --git a/source/parser/rmt_rdf_data_stream.h b/source/parser/rmt_rdf_data_stream.h index 479ce1d..9edb9af 100644 --- a/source/parser/rmt_rdf_data_stream.h +++ b/source/parser/rmt_rdf_data_stream.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of the RFD Data Stream chunk parser. diff --git a/source/parser/rmt_rdf_dd_event_info.cpp b/source/parser/rmt_rdf_dd_event_info.cpp index a2e87dd..df8dee5 100644 --- a/source/parser/rmt_rdf_dd_event_info.cpp +++ b/source/parser/rmt_rdf_dd_event_info.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the RDF DD Event Information chunk parser. diff --git a/source/parser/rmt_rdf_dd_event_info.h b/source/parser/rmt_rdf_dd_event_info.h index 4801c8d..1c8228d 100644 --- a/source/parser/rmt_rdf_dd_event_info.h +++ b/source/parser/rmt_rdf_dd_event_info.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of the RDF DD Event Information chunk parser. diff --git a/source/parser/rmt_rdf_gpu_mem_segment_info.cpp b/source/parser/rmt_rdf_gpu_mem_segment_info.cpp index 458c0f7..6aa104a 100644 --- a/source/parser/rmt_rdf_gpu_mem_segment_info.cpp +++ b/source/parser/rmt_rdf_gpu_mem_segment_info.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the RDF Heap info chunk parser. diff --git a/source/parser/rmt_rdf_gpu_mem_segment_info.h b/source/parser/rmt_rdf_gpu_mem_segment_info.h index 67fd4bb..c12cb1e 100644 --- a/source/parser/rmt_rdf_gpu_mem_segment_info.h +++ b/source/parser/rmt_rdf_gpu_mem_segment_info.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of the RDF GPU Memory Segment (heap) Information chunk parser. diff --git a/source/parser/rmt_rdf_snapshot_index.cpp b/source/parser/rmt_rdf_snapshot_index.cpp index a12942d..a57d496 100644 --- a/source/parser/rmt_rdf_snapshot_index.cpp +++ b/source/parser/rmt_rdf_snapshot_index.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the RFD Snapshot Info chunk. Loads the chunk data into a buffer. diff --git a/source/parser/rmt_rdf_snapshot_index.h b/source/parser/rmt_rdf_snapshot_index.h index 70d4d96..83880a0 100644 --- a/source/parser/rmt_rdf_snapshot_index.h +++ b/source/parser/rmt_rdf_snapshot_index.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of the RFD Snapshot Index chunk. diff --git a/source/parser/rmt_rdf_snapshot_info.cpp b/source/parser/rmt_rdf_snapshot_info.cpp index 713c2a5..99905d0 100644 --- a/source/parser/rmt_rdf_snapshot_info.cpp +++ b/source/parser/rmt_rdf_snapshot_info.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of the RFD Snapshot Info chunk. Loads the chunk data into a buffer. diff --git a/source/parser/rmt_rdf_snapshot_info.h b/source/parser/rmt_rdf_snapshot_info.h index 89c52e9..7f8c087 100644 --- a/source/parser/rmt_rdf_snapshot_info.h +++ b/source/parser/rmt_rdf_snapshot_info.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of the RFD Snapshot Info chunk. diff --git a/source/parser/rmt_string_memory_pool.cpp b/source/parser/rmt_string_memory_pool.cpp index 0237654..eba3f46 100644 --- a/source/parser/rmt_string_memory_pool.cpp +++ b/source/parser/rmt_string_memory_pool.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of functions for a dynamic memory pool diff --git a/source/parser/rmt_string_memory_pool.h b/source/parser/rmt_string_memory_pool.h index f8fce2e..d92805d 100644 --- a/source/parser/rmt_string_memory_pool.h +++ b/source/parser/rmt_string_memory_pool.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of structures and functions for a dynamic memory pool diff --git a/source/parser/rmt_token.cpp b/source/parser/rmt_token.cpp index c1ccfef..ac3fb1c 100644 --- a/source/parser/rmt_token.cpp +++ b/source/parser/rmt_token.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of functions related to RMT token structures. @@ -92,6 +92,7 @@ void RmtTokenCopy(RmtToken* dest, const RmtToken* src) dest->userdata_token.size_in_bytes = src->userdata_token.size_in_bytes; dest->userdata_token.userdata_type = src->userdata_token.userdata_type; dest->userdata_token.time_delay = src->userdata_token.time_delay; + dest->userdata_token.implicit_resource_type = src->userdata_token.implicit_resource_type; if ((dest->userdata_token.userdata_type == kRmtUserdataTypeName || dest->userdata_token.userdata_type == kRmtUserdataTypeName_V2) && (dest->userdata_token.size_in_bytes > 0)) diff --git a/source/parser/rmt_token.h b/source/parser/rmt_token.h index 7ccf72e..be5094c 100644 --- a/source/parser/rmt_token.h +++ b/source/parser/rmt_token.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definitions of the RMT token. @@ -74,6 +74,7 @@ typedef struct RmtTokenUserdata resource_identifier; ///< The identifier used to match a name to a non-DX resource, only valid when usedataType is RMT_USERDATA_TYPE_NAME. RmtCorrelationIdentifier correlation_identifier; ///< The identifier used to match correlation ID for DX traces. RmtResourceIdentifier original_resource_identifier; ///< The Original Resource ID contained in the RESOURCE_CREATE token. + RmtImplicitResourceType implicit_resource_type; ///< The type of implicit resource. } RmtTokenUserdata; /// A structure encapsulating misc data. diff --git a/source/parser/rmt_token_heap.cpp b/source/parser/rmt_token_heap.cpp index c2c588e..50ab6b3 100644 --- a/source/parser/rmt_token_heap.cpp +++ b/source/parser/rmt_token_heap.cpp @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Implementation of a priority queue data structure. diff --git a/source/parser/rmt_token_heap.h b/source/parser/rmt_token_heap.h index c33fea1..475eb0d 100644 --- a/source/parser/rmt_token_heap.h +++ b/source/parser/rmt_token_heap.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief A priority queue data structure for RmtToken structures. diff --git a/source/parser/rmt_types.h b/source/parser/rmt_types.h index 45df0c2..1b85687 100644 --- a/source/parser/rmt_types.h +++ b/source/parser/rmt_types.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Definition of types used throughout the RMT code. diff --git a/source/parser/rmt_util.h b/source/parser/rmt_util.h index c98d625..fda9594 100644 --- a/source/parser/rmt_util.h +++ b/source/parser/rmt_util.h @@ -1,5 +1,5 @@ //============================================================================= -// Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. /// @author AMD Developer Tools Team /// @file /// @brief Utility macro definitions. diff --git a/source/third_party/pevents/LICENSE b/source/third_party/pevents/LICENSE index 8a92787..a22e53d 100644 --- a/source/third_party/pevents/LICENSE +++ b/source/third_party/pevents/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 2011 - 2015 by NeoSmart Technologies +Copyright (C) 2011 - 2022 by NeoSmart Technologies Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/source/third_party/pevents/README b/source/third_party/pevents/README deleted file mode 100644 index 193fc4e..0000000 --- a/source/third_party/pevents/README +++ /dev/null @@ -1,79 +0,0 @@ -pevents is a cross-platform C++ library meant to provide an -implementation of the WIN32 events for POSIX systems. pevents is built -on pthreads and provides *most* of the functionality of both manual- -and auto-reset events on Windows, most-notably including simultaneous -waits on multiple events (à la WaitForMultipleObjects). pevents is -also free of spurious wakeups - returns from waits are guaranteed -correct. - -pevents also doubles as a thin, sane wrapper for CreateEvent() & co. on -Windows, meaning you can use pevents directly in your cross-platform -code without #ifdefs for Windows/pthreads. - -pevents is developed and maintained by Mahmoud Al-Qudsi - of NeoSmart Technologies - -While POSIX condition variables (pthread_cond_t) and WIN32 events both -provide the essential building blocks of the synchronization primitives -required to write multithreaded code with signaling, the nature of the -differences between the two have lent their way towards creating -different synchronization and multithreaded-programming paradigms. - -Developers accustomed to WIN32 events might have a hard time -transitioning to condition variables; pevents aims to ease the -transition for Windows developers looking to write multithreaded code on -*nix by providing a familiar synchronization primitive that will allow -them to duplicate the essential features of WIN32 auto/manual-reset -events. - -As mentioned earlier, pevents provides most of the functionality of -WIN32 events. The only features not included are only named events and -support for security attributes. - -Usage: - -pevents comes with two APIs: one along the lines of WIN32 functions and -the other for those more comfortable with pthread functions. They are -identical underneath the hood. - -WIN32-style pevents API: - - neosmart_event_t CreateEvent(bool manualReset, bool initialState); - - int DestroyEvent(neosmart_event_t event); - - int WaitForEvent(neosmart_event_t event, uint64_t milliseconds); - - int WaitForMultipleEvents(neosmart_event_t *events, int count, - bool waitAll, uint64_t milliseconds); - - int WaitForMultipleEvents(neosmart_event_t *events, int count, - bool waitAll, uint64_t milliseconds, int &index); - - int SetEvent(neosmart_event_t event); - - int ResetEvent(neosmart_event_t event); - - int PulseEvent(neosmart_event_t event); - -All the code is contained within pevents.cpp and pevents.h. You should -include these two files in your project as needed. All functions are in -the neosmart namespace. (Windows users should use win32.cpp instead of -pevents.cpp) - -Compilation options: - -The following preprocessor definitions may be defined (-DOPTION) at -compile time to enable different features. - -WFMO: Enables WFMO support in pevents. It is recommended to only compile -with WFMO support if you are taking advantage of the -WaitForMultipleEvents function, as it adds a (small) overhead to all -event objects. - -PULSE: Enables the PulseEvent function. PulseEvent() on Windows is -fundamentally broken and should not be relied upon — it will almost -never do what you think you're doing when you call it. pevents includes -this function only to make porting existing (flawed) code from WIN32 to -*nix platforms easier, and this function is not compiled into pevents by -default. diff --git a/source/third_party/pevents/README.md b/source/third_party/pevents/README.md new file mode 100644 index 0000000..0b372c9 --- /dev/null +++ b/source/third_party/pevents/README.md @@ -0,0 +1,119 @@ +# pevents + +`pevents` is a cross-platform low-level library meant to provide an +implementation of the WIN32 events for POSIX systems. pevents is built +on pthreads and provides *most* of the functionality of both manual- +and auto-reset events on Windows, most-notably including simultaneous +waits on multiple events (à la `WaitForMultipleObjects`). + +pevents also doubles as a thin, sane wrapper for `CreateEvent()` & co. on +Windows, meaning you can use pevents directly in your cross-platform +code without `#ifdefs` for Windows/pthreads. + +## License and Authorship + +pevents is developed and maintained by Mahmoud Al-Qudsi +\<[mqudsi@neosmart.net](mailto:mqudsi@neosmart.net)\> of NeoSmart Technologies +\<[https://neosmart.net/](https://neosmart.net/)\> and is distributed under the +open source MIT public license. Refer to the `LICENSE` file for more information. + +## About pevents + +While POSIX condition variables (`pthread_cond_t`) and WIN32 events both +provide the essential building blocks of the synchronization primitives +required to write multithreaded code with signaling, the nature of the +differences between the two have lent their way towards creating +different synchronization and multithreaded-programming paradigms. + +Developers accustomed to WIN32 events might have a hard time +transitioning to condition variables; pevents aims to ease the +transition for Windows developers looking to write multithreaded code on +*nix by providing a familiar synchronization primitive that will allow +them to duplicate the essential features of WIN32 auto/manual-reset +events. + +As mentioned earlier, pevents provides most of the functionality of +WIN32 events. The only features not included are only named events and +support for security attributes. To the author's best knowledge, this is the only +implementation of WIN32 events available for Linux and other posix platforms +that provides support for simultaneously waiting on multiple events. + +Depending on your needs, we've been told that pevents may be used as a lightweight +alternative to libuv/libev while still allowing your code to embrace asynchronous event +handling with ease. + +### Supported platforms + +pevents has been used as an extremely simple and lightweight cross-platform synchronization +library in code used across multiple platforms (including Windows, FreeBSD, Linux, macOS, +iOS, Android, and more). +## pevents API + +The pevents API is modeled after the Windows `CreateEvent()`, `WaitForSingleObject()`, +and `WaitForMultipleObjects()` functions. Users familiar with WIN32 events +should have no problem switching the codebase over to the pevents API. + +Additionally, pevents is also free of spurious wakeups - returns from waits are guaranteed +correct¹. + +¹ *Spurious wakeups are a normal part of system programming under +Linux, and a common pitfall for developers coming from the Windows world.* + +```cpp +neosmart_event_t CreateEvent(bool manualReset, bool initialState); + +int DestroyEvent(neosmart_event_t event); + +int WaitForEvent(neosmart_event_t event, uint64_t milliseconds); + +int WaitForMultipleEvents(neosmart_event_t *events, int count, + bool waitAll, uint64_t milliseconds); + +int WaitForMultipleEvents(neosmart_event_t *events, int count, + bool waitAll, uint64_t milliseconds, int &index); + +int SetEvent(neosmart_event_t event); + +int ResetEvent(neosmart_event_t event); + +int PulseEvent(neosmart_event_t event); +``` + +## Building and using pevents + +All the code is contained within `pevents.cpp` and `pevents.h`. You should +include these two files in your project as needed. All functions are in +the `neosmart` namespace. + +### Code structure + +* Core `pevents` code is in the `src/` directory +* Unit tests (deployable via meson) are in `tests/` +* A sample cross-platform application demonstrating the usage of pevents can be found +in the `examples/` folder. More examples are to come. (Pull requests welcomed!) + +### Optional build system + +Experimental support for building pevents via the meson build system has recently landed. +Currently, this is only used to support automated building/testing of pevents core and +its supporting utilities and unit tests. To repeat: do not worry about the build system, +pevents is purposely written in plain C/C++ and avoids the need for complex configuration +or platform-dependent build instructions. + +### Compilation options: + +The following preprocessor definitions may be defined (`-DOPTION`) at +compile time to enable different features. + +* `WFMO`: Enables WFMO support in pevents. It is recommended to only compile +with WFMO support if you are taking advantage of the +`WaitForMultipleEvents` function, as it adds a (small) overhead to all +event objects. + +* `PULSE`: Enables the `PulseEvent` function. `PulseEvent()` on Windows is +fundamentally broken and should not be relied upon — it will almost +never do what you think you're doing when you call it. pevents includes +this function only to make porting existing (flawed) code from WIN32 to +*nix platforms easier, and this function is not compiled into pevents by +default. + diff --git a/source/third_party/pevents/pevents.cpp b/source/third_party/pevents/pevents.cpp deleted file mode 100644 index b8c2296..0000000 --- a/source/third_party/pevents/pevents.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* - * WIN32 Events for POSIX - * Author: Mahmoud Al-Qudsi - * Copyright (C) 2011 - 2015 by NeoSmart Technologies - * This code is released under the terms of the MIT License -*/ - -#ifndef _WIN32 - -#include "pevents.h" -#include -#include -#include -#include -#ifdef WFMO -#include -#include -#endif - -#define UNUSED(x) ((void)(x)) - -namespace neosmart -{ -#ifdef WFMO - //Each call to WaitForMultipleObjects initializes a neosmart_wfmo_t object which tracks - //the progress of the caller's multi-object wait and dispatches responses accordingly. - //One neosmart_wfmo_t struct is shared for all events in a single WFMO call - struct neosmart_wfmo_t_ - { - pthread_mutex_t Mutex; - pthread_cond_t CVariable; - int RefCount; - union - { - int FiredEvent; //WFSO - int EventsLeft; //WFMO - } Status; - bool WaitAll; - bool StillWaiting; - - void Destroy() - { - pthread_mutex_destroy(&Mutex); - pthread_cond_destroy(&CVariable); - } - }; - typedef neosmart_wfmo_t_ *neosmart_wfmo_t; - - //A neosmart_wfmo_info_t object is registered with each event waited on in a WFMO - //This reference to neosmart_wfmo_t_ is how the event knows whom to notify when triggered - struct neosmart_wfmo_info_t_ - { - neosmart_wfmo_t Waiter; - int WaitIndex; - }; - typedef neosmart_wfmo_info_t_ *neosmart_wfmo_info_t; -#endif - - //The basic event structure, passed to the caller as an opaque pointer when creating events - struct neosmart_event_t_ - { - pthread_cond_t CVariable; - pthread_mutex_t Mutex; - bool AutoReset; - bool State; -#ifdef WFMO - std::deque RegisteredWaits; -#endif - }; - -#ifdef WFMO - bool RemoveExpiredWaitHelper(neosmart_wfmo_info_t_ wait) - { - int result = pthread_mutex_trylock(&wait.Waiter->Mutex); - - if (result == EBUSY) - { - return false; - } - - assert(result == 0); - - if (wait.Waiter->StillWaiting == false) - { - --wait.Waiter->RefCount; - assert(wait.Waiter->RefCount >= 0); - if (wait.Waiter->RefCount == 0) - { - wait.Waiter->Destroy(); - delete wait.Waiter; - } - else - { - result = pthread_mutex_unlock(&wait.Waiter->Mutex); - assert(result == 0); - } - - return true; - } - - result = pthread_mutex_unlock(&wait.Waiter->Mutex); - assert(result == 0); - - return false; - } -#endif - - neosmart_event_t CreateEvent(bool manualReset, bool initialState) - { - neosmart_event_t event = new neosmart_event_t_; - - int result = pthread_cond_init(&event->CVariable, 0); - UNUSED(result); - assert(result == 0); - - result = pthread_mutex_init(&event->Mutex, 0); - assert(result == 0); - - event->State = false; - event->AutoReset = !manualReset; - - if (initialState) - { - result = SetEvent(event); - assert(result == 0); - } - - return event; - } - - int UnlockedWaitForEvent(neosmart_event_t event, uint64_t milliseconds) - { - int result = 0; - if (!event->State) - { - //Zero-timeout event state check optimization - if (milliseconds == 0) - { - return WAIT_TIMEOUT; - } - - timespec ts; - if (milliseconds != (uint64_t) -1) - { - timeval tv; - gettimeofday(&tv, NULL); - - uint64_t nanoseconds = ((uint64_t) tv.tv_sec) * 1000 * 1000 * 1000 + milliseconds * 1000 * 1000 + ((uint64_t) tv.tv_usec) * 1000; - - ts.tv_sec = nanoseconds / 1000 / 1000 / 1000; - ts.tv_nsec = (nanoseconds - ((uint64_t) ts.tv_sec) * 1000 * 1000 * 1000); - } - - do - { - //Regardless of whether it's an auto-reset or manual-reset event: - //wait to obtain the event, then lock anyone else out - if (milliseconds != (uint64_t) -1) - { - result = pthread_cond_timedwait(&event->CVariable, &event->Mutex, &ts); - } - else - { - result = pthread_cond_wait(&event->CVariable, &event->Mutex); - } - } while (result == 0 && !event->State); - - if (result == 0 && event->AutoReset) - { - //We've only accquired the event if the wait succeeded - event->State = false; - } - } - else if (event->AutoReset) - { - //It's an auto-reset event that's currently available; - //we need to stop anyone else from using it - result = 0; - event->State = false; - } - //Else we're trying to obtain a manual reset event with a signaled state; - //don't do anything - - return result; - } - - int WaitForEvent(neosmart_event_t event, uint64_t milliseconds) - { - int tempResult; - if (milliseconds == 0) - { - tempResult = pthread_mutex_trylock(&event->Mutex); - if (tempResult == EBUSY) - { - return WAIT_TIMEOUT; - } - } - else - { - tempResult = pthread_mutex_lock(&event->Mutex); - } - - assert(tempResult == 0); - - int result = UnlockedWaitForEvent(event, milliseconds); - - tempResult = pthread_mutex_unlock(&event->Mutex); - assert(tempResult == 0); - - return result; - } - -#ifdef WFMO - int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds) - { - int unused; - return WaitForMultipleEvents(events, count, waitAll, milliseconds, unused); - } - - int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds, int &waitIndex) - { - neosmart_wfmo_t wfmo = new neosmart_wfmo_t_; - - int result = 0; - int tempResult = pthread_mutex_init(&wfmo->Mutex, 0); - assert(tempResult == 0); - - tempResult = pthread_cond_init(&wfmo->CVariable, 0); - assert(tempResult == 0); - - neosmart_wfmo_info_t_ waitInfo; - waitInfo.Waiter = wfmo; - waitInfo.WaitIndex = -1; - - wfmo->WaitAll = waitAll; - wfmo->StillWaiting = true; - wfmo->RefCount = 1; - - if (waitAll) - { - wfmo->Status.EventsLeft = count; - } - else - { - wfmo->Status.FiredEvent = -1; - } - - tempResult = pthread_mutex_lock(&wfmo->Mutex); - assert(tempResult == 0); - - bool done = false; - waitIndex = -1; - - for (int i = 0; i < count; ++i) - { - waitInfo.WaitIndex = i; - - //Must not release lock until RegisteredWait is potentially added - tempResult = pthread_mutex_lock(&events[i]->Mutex); - assert(tempResult == 0); - - //Before adding this wait to the list of registered waits, let's clean up old, expired waits while we have the event lock anyway - events[i]->RegisteredWaits.erase(std::remove_if (events[i]->RegisteredWaits.begin(), events[i]->RegisteredWaits.end(), RemoveExpiredWaitHelper), events[i]->RegisteredWaits.end()); - - if (UnlockedWaitForEvent(events[i], 0) == 0) - { - tempResult = pthread_mutex_unlock(&events[i]->Mutex); - assert(tempResult == 0); - - if (waitAll) - { - --wfmo->Status.EventsLeft; - assert(wfmo->Status.EventsLeft >= 0); - } - else - { - wfmo->Status.FiredEvent = i; - waitIndex = i; - done = true; - break; - } - } - else - { - events[i]->RegisteredWaits.push_back(waitInfo); - ++wfmo->RefCount; - - tempResult = pthread_mutex_unlock(&events[i]->Mutex); - assert(tempResult == 0); - } - } - - timespec ts; - if (!done) - { - if (milliseconds == 0) - { - result = WAIT_TIMEOUT; - done = true; - } - else if (milliseconds != (uint64_t) -1) - { - timeval tv; - gettimeofday(&tv, NULL); - - uint64_t nanoseconds = ((uint64_t) tv.tv_sec) * 1000 * 1000 * 1000 + milliseconds * 1000 * 1000 + ((uint64_t) tv.tv_usec) * 1000; - - ts.tv_sec = nanoseconds / 1000 / 1000 / 1000; - ts.tv_nsec = (nanoseconds - ((uint64_t) ts.tv_sec) * 1000 * 1000 * 1000); - } - } - - while (!done) - { - //One (or more) of the events we're monitoring has been triggered? - - //If we're waiting for all events, assume we're done and check if there's an event that hasn't fired - //But if we're waiting for just one event, assume we're not done until we find a fired event - done = (waitAll && wfmo->Status.EventsLeft == 0) || (!waitAll && wfmo->Status.FiredEvent != -1); - - if (!done) - { - if (milliseconds != (uint64_t) -1) - { - result = pthread_cond_timedwait(&wfmo->CVariable, &wfmo->Mutex, &ts); - } - else - { - result = pthread_cond_wait(&wfmo->CVariable, &wfmo->Mutex); - } - - if (result != 0) - { - break; - } - } - } - - waitIndex = wfmo->Status.FiredEvent; - wfmo->StillWaiting = false; - - --wfmo->RefCount; - assert(wfmo->RefCount >= 0); - if (wfmo->RefCount == 0) - { - wfmo->Destroy(); - delete wfmo; - } - else - { - tempResult = pthread_mutex_unlock(&wfmo->Mutex); - assert(tempResult == 0); - } - - return result; - } -#endif - - int DestroyEvent(neosmart_event_t event) - { - int result = 0; - UNUSED(result); - -#ifdef WFMO - result = pthread_mutex_lock(&event->Mutex); - assert(result == 0); - event->RegisteredWaits.erase(std::remove_if (event->RegisteredWaits.begin(), event->RegisteredWaits.end(), RemoveExpiredWaitHelper), event->RegisteredWaits.end()); - result = pthread_mutex_unlock(&event->Mutex); - assert(result == 0); -#endif - - result = pthread_cond_destroy(&event->CVariable); - assert(result == 0); - - result = pthread_mutex_destroy(&event->Mutex); - assert(result == 0); - - delete event; - - return 0; - } - - int SetEvent(neosmart_event_t event) - { - int result = pthread_mutex_lock(&event->Mutex); - UNUSED(result); - assert(result == 0); - - event->State = true; - - //Depending on the event type, we either trigger everyone or only one - if (event->AutoReset) - { -#ifdef WFMO - while (!event->RegisteredWaits.empty()) - { - neosmart_wfmo_info_t i = &event->RegisteredWaits.front(); - - result = pthread_mutex_lock(&i->Waiter->Mutex); - assert(result == 0); - - --i->Waiter->RefCount; - assert(i->Waiter->RefCount >= 0); - if (!i->Waiter->StillWaiting) - { - if (i->Waiter->RefCount == 0) - { - i->Waiter->Destroy(); - delete i->Waiter; - } - else - { - result = pthread_mutex_unlock(&i->Waiter->Mutex); - assert(result == 0); - } - event->RegisteredWaits.pop_front(); - continue; - } - - event->State = false; - - if (i->Waiter->WaitAll) - { - --i->Waiter->Status.EventsLeft; - assert(i->Waiter->Status.EventsLeft >= 0); - //We technically should do i->Waiter->StillWaiting = Waiter->Status.EventsLeft != 0 - //but the only time it'll be equal to zero is if we're the last event, so no one - //else will be checking the StillWaiting flag. We're good to go without it. - } - else - { - i->Waiter->Status.FiredEvent = i->WaitIndex; - i->Waiter->StillWaiting = false; - } - - result = pthread_mutex_unlock(&i->Waiter->Mutex); - assert(result == 0); - - result = pthread_cond_signal(&i->Waiter->CVariable); - assert(result == 0); - - event->RegisteredWaits.pop_front(); - - result = pthread_mutex_unlock(&event->Mutex); - assert(result == 0); - - return 0; - } -#endif - //event->State can be false if compiled with WFMO support - if (event->State) - { - result = pthread_mutex_unlock(&event->Mutex); - assert(result == 0); - - result = pthread_cond_signal(&event->CVariable); - assert(result == 0); - - return 0; - } - } - else - { -#ifdef WFMO - for (size_t i = 0; i < event->RegisteredWaits.size(); ++i) - { - neosmart_wfmo_info_t info = &event->RegisteredWaits[i]; - - result = pthread_mutex_lock(&info->Waiter->Mutex); - assert(result == 0); - - --info->Waiter->RefCount; - assert(info->Waiter->RefCount >= 0); - - if (!info->Waiter->StillWaiting) - { - if (info->Waiter->RefCount == 0) - { - info->Waiter->Destroy(); - delete info->Waiter; - } - else - { - result = pthread_mutex_unlock(&info->Waiter->Mutex); - assert(result == 0); - } - continue; - } - - if (info->Waiter->WaitAll) - { - --info->Waiter->Status.EventsLeft; - assert(info->Waiter->Status.EventsLeft >= 0); - //We technically should do i->Waiter->StillWaiting = Waiter->Status.EventsLeft != 0 - //but the only time it'll be equal to zero is if we're the last event, so no one - //else will be checking the StillWaiting flag. We're good to go without it. - } - else - { - info->Waiter->Status.FiredEvent = info->WaitIndex; - info->Waiter->StillWaiting = false; - } - - result = pthread_mutex_unlock(&info->Waiter->Mutex); - assert(result == 0); - - result = pthread_cond_signal(&info->Waiter->CVariable); - assert(result == 0); - } - event->RegisteredWaits.clear(); -#endif - result = pthread_mutex_unlock(&event->Mutex); - assert(result == 0); - - result = pthread_cond_broadcast(&event->CVariable); - assert(result == 0); - } - - return 0; - } - - int ResetEvent(neosmart_event_t event) - { - int result = pthread_mutex_lock(&event->Mutex); - UNUSED(result); - assert(result == 0); - - event->State = false; - - result = pthread_mutex_unlock(&event->Mutex); - assert(result == 0); - - return 0; - } - -#ifdef PULSE - int PulseEvent(neosmart_event_t event) - { - //This may look like it's a horribly inefficient kludge with the sole intention of reducing code duplication, - //but in reality this is what any PulseEvent() implementation must look like. The only overhead (function - //calls aside, which your compiler will likely optimize away, anyway), is if only WFMO auto-reset waits are active - //there will be overhead to unnecessarily obtain the event mutex for ResetEvent() after. In all other cases (being - //no pending waits, WFMO manual-reset waits, or any WFSO waits), the event mutex must first be released for the - //waiting thread to resume action prior to locking the mutex again in order to set the event state to unsignaled, - //or else the waiting threads will loop back into a wait (due to checks for spurious CVariable wakeups). - - int result = SetEvent(event); - assert(result == 0); - result = ResetEvent(event); - assert(result == 0); - - return 0; - } -#endif -} - -#endif //_WIN32 diff --git a/source/third_party/pevents/pevents.h b/source/third_party/pevents/pevents.h deleted file mode 100644 index bf05163..0000000 --- a/source/third_party/pevents/pevents.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * WIN32 Events for POSIX - * Author: Mahmoud Al-Qudsi - * Copyright (C) 2011 - 2015 by NeoSmart Technologies - * This code is released under the terms of the MIT License -*/ - -#pragma once - -#if defined(_WIN32) && !defined(CreateEvent) -#error Must include Windows.h prior to including pevents.h! -#endif -#ifndef WAIT_TIMEOUT -#include -#define WAIT_TIMEOUT ETIMEDOUT -#endif - -#include - -namespace neosmart -{ - //Type declarations - struct neosmart_event_t_; - typedef neosmart_event_t_ * neosmart_event_t; - - //WIN32-style functions - neosmart_event_t CreateEvent(bool manualReset = false, bool initialState = false); - int DestroyEvent(neosmart_event_t event); - int WaitForEvent(neosmart_event_t event, uint64_t milliseconds = -1); - int SetEvent(neosmart_event_t event); - int ResetEvent(neosmart_event_t event); -#ifdef WFMO - int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds); - int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds, int &index); -#endif -#ifdef PULSE - int PulseEvent(neosmart_event_t event); -#endif - - //POSIX-style functions - //TBD -} diff --git a/source/third_party/pevents/sample.cpp b/source/third_party/pevents/sample.cpp deleted file mode 100644 index 6a5b74f..0000000 --- a/source/third_party/pevents/sample.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * WIN32 Events for POSIX - * Author: Mahmoud Al-Qudsi - * Copyright (C) 2011 - 2015 by NeoSmart Technologies - * This code is released under the terms of the MIT License -*/ - -#include -#include -#include -#include -#include -#include -#include -//On Windows, you must include Winbase.h/Synchapi.h/Windows.h before pevents.h -#ifdef _WIN32 -#include -#endif -#include "pevents.h" - -using namespace neosmart; -using namespace std; - -neosmart_event_t events[3]; //letters, numbers, abort -std::atomic interrupted { false }; -char letter = '?'; -int number = -1; - -char lastChar = '\0'; -int lastNum = -1; - -void intHandler(int sig) { - interrupted = true; - //unfortunately you can't use SetEvent here because posix signal handlers - //shouldn't use any non-reentrant code (like printf) - //on x86/x64, std::atomic is just a fancy way of doing a memory - //barrier and nothing more, so it is safe -} - -void letters() -{ - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution dis(0, 3000); - for (uint32_t i = 0; WaitForEvent(events[2], dis(gen)) == WAIT_TIMEOUT; ++i) - { - letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%26]; - SetEvent(events[0]); - } -} - -void numbers() -{ - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution dis(0, 3000); - for (uint32_t i = 0; WaitForEvent(events[2], dis(gen)) == WAIT_TIMEOUT; ++i) - { - number = i; - SetEvent(events[1]); - } -} - -int main() -{ - events[0] = CreateEvent(); //letters auto-reset event - events[1] = CreateEvent(); //numbers auto-reset event - events[2] = CreateEvent(true); //abort manual-reset event - - //after the abort event has been created - struct sigaction act = {0}; - act.sa_handler = intHandler; //trigger abort on ctrl+c - sigaction(SIGINT, &act, NULL); - - std::thread thread1(letters); - std::thread thread2(numbers); - - for (uint32_t i = 0; lastChar != 'Z'; ++i) - { - if (interrupted) - { - printf("Interrupt triggered.. Aborting!\n"); - break; - } - - int index = -1; - int result = WaitForMultipleEvents(events, 2, false, -1, index); - - if (result == WAIT_TIMEOUT) - { - cout << "Timeout!" << endl; - } - else if (result != 0) - { - cout << "Error in wait!" << endl; - } - else if (index == 0) - { - assert(lastChar != letter); - cout << letter << endl; - lastChar = letter; - } - else if (index == 1) - { - assert(lastNum != number); - cout << number << endl; - lastNum = number; - } - else - { - cout << "ERROR! Unexpected index: " << index << endl; - exit(-1); - } - } - - //You can't just DestroyEvent() and exit - it'll segfault - //That's because letters() and numbers() will call SetEvent on a destroyed event - //You must *never* call SetEvent/ResetEvent on a destroyed event! - //So we set an abort event and wait for the helper threads to exit - - //Set the abort - SetEvent(events[2]); - - thread1.join(); - thread2.join(); - - for (auto event : events) - { - DestroyEvent(event); - } -} diff --git a/source/third_party/pevents/src/pevents.cpp b/source/third_party/pevents/src/pevents.cpp new file mode 100644 index 0000000..e96ec69 --- /dev/null +++ b/source/third_party/pevents/src/pevents.cpp @@ -0,0 +1,664 @@ +/* + * WIN32 Events for POSIX + * Author: Mahmoud Al-Qudsi + * Copyright (C) 2011 - 2022 by NeoSmart Technologies + * SPDX-License-Identifier: MIT + */ + +#ifndef _WIN32 + +#include "pevents.h" +#include +#include +#include +#include +#include +#include +#ifdef WFMO +#include +#include +#endif + +namespace neosmart { +#ifdef WFMO + // Each call to WaitForMultipleObjects initializes a neosmart_wfmo_t object which tracks + // the progress of the caller's multi-object wait and dispatches responses accordingly. + // One neosmart_wfmo_t struct is shared for all events in a single WFMO call + struct neosmart_wfmo_t_ { + pthread_mutex_t Mutex; + pthread_cond_t CVariable; + std::atomic RefCount; + union { + int FiredEvent; // WFSO + int EventsLeft; // WFMO + } Status; + bool WaitAll; + std::atomic StillWaiting; + + void Destroy() { + pthread_mutex_destroy(&Mutex); + pthread_cond_destroy(&CVariable); + } + }; + typedef neosmart_wfmo_t_ *neosmart_wfmo_t; + + // A neosmart_wfmo_info_t object is registered with each event waited on in a WFMO + // This reference to neosmart_wfmo_t_ is how the event knows whom to notify when triggered + struct neosmart_wfmo_info_t_ { + neosmart_wfmo_t Waiter; + int WaitIndex; + }; + typedef neosmart_wfmo_info_t_ *neosmart_wfmo_info_t; +#endif // WFMO + + // The basic event structure, passed to the caller as an opaque pointer when creating events + struct neosmart_event_t_ { + pthread_cond_t CVariable; + pthread_mutex_t Mutex; + bool AutoReset; + std::atomic State; +#ifdef WFMO + std::deque RegisteredWaits; +#endif + }; + +#ifdef WFMO + static bool RemoveExpiredWaitHelper(neosmart_wfmo_info_t_ wait) { + if (wait.Waiter->StillWaiting.load(std::memory_order_relaxed)) { + return false; + } + + int ref_count = wait.Waiter->RefCount.fetch_sub(1, std::memory_order_acq_rel); + assert(ref_count > 0); + + if (ref_count == 1) { + wait.Waiter->Destroy(); + delete wait.Waiter; + } + return true; + } +#endif // WFMO + + neosmart_event_t CreateEvent(bool manualReset, bool initialState) { + neosmart_event_t event = new neosmart_event_t_; + + int result = pthread_cond_init(&event->CVariable, 0); + assert(result == 0); + + result = pthread_mutex_init(&event->Mutex, 0); + assert(result == 0); + + event->AutoReset = !manualReset; + // memory_order_release: if `initialState == true`, allow a load with acquire semantics to + // see the value. + event->State.store(initialState, std::memory_order_release); + + return event; + } + + static int UnlockedWaitForEvent(neosmart_event_t event, uint64_t milliseconds) { + int result = 0; + // memory_order_relaxed: `State` is only set to true with the mutex held, and we require + // that this function only be called after the mutex is obtained. + if (!event->State.load(std::memory_order_relaxed)) { + // Zero-timeout event state check optimization + if (milliseconds == 0) { + return WAIT_TIMEOUT; + } + + timespec ts; + if (milliseconds != WAIT_INFINITE) { + timeval tv; + gettimeofday(&tv, NULL); + + uint64_t nanoseconds = ((uint64_t)tv.tv_sec) * 1000 * 1000 * 1000 + + milliseconds * 1000 * 1000 + ((uint64_t)tv.tv_usec) * 1000; + + ts.tv_sec = (time_t) (nanoseconds / 1000 / 1000 / 1000); + ts.tv_nsec = (long) (nanoseconds - ((uint64_t)ts.tv_sec) * 1000 * 1000 * 1000); + } + + do { + // Regardless of whether it's an auto-reset or manual-reset event: + // wait to obtain the event, then lock anyone else out + if (milliseconds != WAIT_INFINITE) { + result = pthread_cond_timedwait(&event->CVariable, &event->Mutex, &ts); + } else { + result = pthread_cond_wait(&event->CVariable, &event->Mutex); + } + // memory_order_relaxed: ordering is guaranteed by the mutex, as `State = true` is + // only ever written with the mutex held. + } while (result == 0 && !event->State.load(std::memory_order_relaxed)); + } else if (event->AutoReset) { + // It's an auto-reset event that's currently available; + // we need to stop anyone else from using it + result = 0; + } + else { + // We're trying to obtain a manual reset event with a signaled state; don't do anything + } + + if (result == 0 && event->AutoReset) { + // We've only accquired the event if the wait succeeded + // memory_order_relaxed: we never act on `State == true` without fully synchronizing + // or grabbing the mutex, so it's OK to use relaxed semantics here. + event->State.store(false, std::memory_order_relaxed); + } + + return result; + } + + int WaitForEvent(neosmart_event_t event, uint64_t milliseconds) { + // Optimization: bypass acquiring the event lock if the state atomic is unavailable. + // memory_order_relaxed: This is just an optimization, it's OK to be biased towards a stale + // value here, and preferable to synchronizing CPU caches to get a more accurate result. + if (milliseconds == 0 && !event->State.load(std::memory_order_relaxed)) { + return WAIT_TIMEOUT; + } + // Optimization: early return in case of success for manual reset events only. + if (!event->AutoReset && event->State.load(std::memory_order_relaxed)) { + // A memory barrier is required here. This is still cheaper than a syscall. + // See https://github.com/neosmart/pevents/issues/18 + if (event->State.load(std::memory_order_acquire)) { + return 0; + } + } + + int tempResult = pthread_mutex_lock(&event->Mutex); + assert(tempResult == 0); + + int result = UnlockedWaitForEvent(event, milliseconds); + + tempResult = pthread_mutex_unlock(&event->Mutex); + assert(tempResult == 0); + + return result; + } + +#ifdef WFMO + int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, + uint64_t milliseconds) { + int unused; + return WaitForMultipleEvents(events, count, waitAll, milliseconds, unused); + } + + int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, + uint64_t milliseconds, int &waitIndex) { + neosmart_wfmo_t wfmo = new neosmart_wfmo_t_; + + int result = 0; + int tempResult = pthread_mutex_init(&wfmo->Mutex, 0); + assert(tempResult == 0); + + tempResult = pthread_cond_init(&wfmo->CVariable, 0); + assert(tempResult == 0); + + neosmart_wfmo_info_t_ waitInfo; + waitInfo.Waiter = wfmo; + waitInfo.WaitIndex = -1; + + if (waitAll) { + wfmo->Status.EventsLeft = count; + } else { + wfmo->Status.FiredEvent = -1; + } + + wfmo->WaitAll = waitAll; + wfmo->StillWaiting.store(true, std::memory_order_release); + // memory_order_release: this is the initial value other threads should see + wfmo->RefCount.store(1 + count, std::memory_order_release); + // Separately keep track of how many refs to decrement after the initialization loop, to + // avoid repeatedly clearing the cache line. + int skipped_refs = 0; + + tempResult = pthread_mutex_lock(&wfmo->Mutex); + assert(tempResult == 0); + + bool done = false; + waitIndex = -1; + + for (int i = 0; i < count; ++i) { + waitInfo.WaitIndex = i; + + // Skip obtaining the mutex for manual reset events. This requires a memory barrier to + // ensure correctness. + bool skipLock = false; + if (!events[i]->AutoReset) { + if (events[i]->State.load(std::memory_order_relaxed) && + events[i]->State.load(std::memory_order_acquire)) { + skipLock = true; + } + } + + if (!skipLock) { + // Must not release lock until RegisteredWait is potentially added + tempResult = pthread_mutex_lock(&events[i]->Mutex); + assert(tempResult == 0); + + // Before adding this wait to the list of registered waits, let's clean up old, + // expired waits while we have the event lock anyway. + events[i]->RegisteredWaits.erase(std::remove_if(events[i]->RegisteredWaits.begin(), + events[i]->RegisteredWaits.end(), + RemoveExpiredWaitHelper), + events[i]->RegisteredWaits.end()); + } + + if (skipLock || UnlockedWaitForEvent(events[i], 0) == 0) { + if (!skipLock) { + tempResult = pthread_mutex_unlock(&events[i]->Mutex); + assert(tempResult == 0); + } + + if (waitAll) { + ++skipped_refs; + --wfmo->Status.EventsLeft; + assert(wfmo->Status.EventsLeft >= 0); + } else { + skipped_refs += (count - i); + wfmo->Status.FiredEvent = i; + waitIndex = i; + done = true; + break; + } + } else { + events[i]->RegisteredWaits.push_back(waitInfo); + + tempResult = pthread_mutex_unlock(&events[i]->Mutex); + assert(tempResult == 0); + } + } + + // We set the `done` flag above in case of WaitAny and at least one event was set. + // But we need to check again here if we were doing a WaitAll or else we'll incorrectly + // return WAIT_TIMEOUT. + if (waitAll && wfmo->Status.EventsLeft == 0) { + done = true; + } + + timespec ts; + if (!done) { + if (milliseconds == 0) { + result = WAIT_TIMEOUT; + done = true; + } else if (milliseconds != WAIT_INFINITE) { + timeval tv; + gettimeofday(&tv, NULL); + + uint64_t nanoseconds = ((uint64_t)tv.tv_sec) * 1000 * 1000 * 1000 + + milliseconds * 1000 * 1000 + ((uint64_t)tv.tv_usec) * 1000; + + ts.tv_sec = (time_t) (nanoseconds / 1000 / 1000 / 1000); + ts.tv_nsec = (long) (nanoseconds - ((uint64_t)ts.tv_sec) * 1000 * 1000 * 1000); + } + } + + while (!done) { + // One (or more) of the events we're monitoring has been triggered? + + // If we're waiting for all events, assume we're done and check if there's an event that + // hasn't fired But if we're waiting for just one event, assume we're not done until we + // find a fired event + done = (waitAll && wfmo->Status.EventsLeft == 0) || + (!waitAll && wfmo->Status.FiredEvent != -1); + + if (!done) { + if (milliseconds != WAIT_INFINITE) { + result = pthread_cond_timedwait(&wfmo->CVariable, &wfmo->Mutex, &ts); + } else { + result = pthread_cond_wait(&wfmo->CVariable, &wfmo->Mutex); + } + + if (result != 0) { + break; + } + } + } + + waitIndex = wfmo->Status.FiredEvent; + // memory_order_relaxed: this is only checked outside the mutex to determine if waiting has + // terminated meaning it's safe to decrement the ref count. If it's true (which we write + // with release semantics), then the mutex is always entered. + wfmo->StillWaiting.store(false, std::memory_order_relaxed); + + tempResult = pthread_mutex_unlock(&wfmo->Mutex); + assert(tempResult == 0); + + // memory_order_seq_cst: Ensure this is run after the wfmo mutex is unlocked + int ref_count = wfmo->RefCount.fetch_sub(1 + skipped_refs, std::memory_order_seq_cst); + assert(ref_count > 0); + if (ref_count == 1 + skipped_refs) { + wfmo->Destroy(); + delete wfmo; + } + + return result; + } +#endif // WFMO + + int DestroyEvent(neosmart_event_t event) { + int result = 0; + +#ifdef WFMO + result = pthread_mutex_lock(&event->Mutex); + assert(result == 0); + event->RegisteredWaits.erase(std::remove_if(event->RegisteredWaits.begin(), + event->RegisteredWaits.end(), + RemoveExpiredWaitHelper), + event->RegisteredWaits.end()); + result = pthread_mutex_unlock(&event->Mutex); + assert(result == 0); +#endif + + result = pthread_cond_destroy(&event->CVariable); + assert(result == 0); + + result = pthread_mutex_destroy(&event->Mutex); + assert(result == 0); + + delete event; + + return 0; + } + + int SetEvent(neosmart_event_t event) { + int result = pthread_mutex_lock(&event->Mutex); + assert(result == 0); + + // Depending on the event type, we either trigger everyone or only one + if (event->AutoReset) { +#ifdef WFMO + while (!event->RegisteredWaits.empty()) { + neosmart_wfmo_info_t i = &event->RegisteredWaits.front(); + + // memory_order_relaxed: this is just an optimization to see if it is OK to skip + // this waiter, and if it's observed to be false then it's OK to bypass the mutex at + // that point. + if (!i->Waiter->StillWaiting.load(std::memory_order_relaxed)) { + int ref_count = i->Waiter->RefCount.fetch_sub(1, std::memory_order_acq_rel); + assert(ref_count > 0); + if (ref_count == 1) { + i->Waiter->Destroy(); + delete i->Waiter; + } + + event->RegisteredWaits.pop_front(); + continue; + } + + result = pthread_mutex_lock(&i->Waiter->Mutex); + assert(result == 0); + + // We have to check `Waiter->StillWaiting` twice, once before locking as an + // optimization to bypass the mutex altogether, and then again after locking the + // WFMO mutex because we could have !waitAll and another event could have ended the + // wait, in which case we must not unlock the same waiter or else a SetEvent() call + // on an auto-reset event may end up with a lost wakeup. + if (!i->Waiter->StillWaiting.load(std::memory_order_relaxed)) { + result = pthread_mutex_unlock(&i->Waiter->Mutex); + assert(result == 0); + + // memory_order_seq_cst: Ensure this is run after the wfmo mutex is unlocked + int ref_count = i->Waiter->RefCount.fetch_sub(1, std::memory_order_seq_cst); + assert(ref_count > 0); + if (ref_count == 1) { + i->Waiter->Destroy(); + delete i->Waiter; + } + + event->RegisteredWaits.pop_front(); + continue; + } + + if (i->Waiter->WaitAll) { + --i->Waiter->Status.EventsLeft; + assert(i->Waiter->Status.EventsLeft >= 0); + // We technically should do i->Waiter->StillWaiting = Waiter->Status.EventsLeft + // != 0 but the only time it'll be equal to zero is if we're the last event, so + // no one else will be checking the StillWaiting flag. We're good to go without + // it. + } else { + i->Waiter->Status.FiredEvent = i->WaitIndex; + // memory_order_relaxed: The flip to false is only lazily observed as an + // optimization to bypass the mutex for cleanup. + i->Waiter->StillWaiting.store(false, std::memory_order_relaxed); + } + + result = pthread_mutex_unlock(&i->Waiter->Mutex); + assert(result == 0); + + result = pthread_cond_signal(&i->Waiter->CVariable); + assert(result == 0); + + // memory_order_seq_cst: Ensure this is run after the wfmo mutex is unlocked + int ref_count = i->Waiter->RefCount.fetch_sub(1, std::memory_order_seq_cst); + assert(ref_count > 0); + if (ref_count == 1) { + i->Waiter->Destroy(); + delete i->Waiter; + } + + event->RegisteredWaits.pop_front(); + + result = pthread_mutex_unlock(&event->Mutex); + assert(result == 0); + + return 0; + } +#endif // WFMO + // memory_order_release: this is the synchronization point for any threads spin-waiting + // for the event to become available. + event->State.store(true, std::memory_order_release); + + result = pthread_mutex_unlock(&event->Mutex); + assert(result == 0); + + result = pthread_cond_signal(&event->CVariable); + assert(result == 0); + + return 0; + } else { // this is a manual reset event + // memory_order_release: this is the synchronization point for any threads spin-waiting + // for the event to become available. + event->State.store(true, std::memory_order_release); +#ifdef WFMO + for (size_t i = 0; i < event->RegisteredWaits.size(); ++i) { + neosmart_wfmo_info_t info = &event->RegisteredWaits[i]; + + // memory_order_relaxed: this is just an optimization to see if it is OK to skip + // this waiter, and if it's observed to be false then it's OK to bypass the mutex at + // that point. + if (!info->Waiter->StillWaiting.load(std::memory_order_relaxed)) { + int ref_count = info->Waiter->RefCount.fetch_sub(1, std::memory_order_acq_rel); + if (ref_count == 1) { + info->Waiter->Destroy(); + delete info->Waiter; + } + continue; + } + + result = pthread_mutex_lock(&info->Waiter->Mutex); + assert(result == 0); + + // Waiter->StillWaiting may have become true by now, but we're just going to pretend + // it hasn't. So long as we hold a reference to the WFMO, this is safe since manual + // reset events are not one-time use. + + if (info->Waiter->WaitAll) { + --info->Waiter->Status.EventsLeft; + assert(info->Waiter->Status.EventsLeft >= 0); + // We technically should do i->Waiter->StillWaiting = Waiter->Status.EventsLeft + // != 0 but the only time it'll be equal to zero is if we're the last event, so + // no one else will be checking the StillWaiting flag. We're good to go without + // it. + } else { + info->Waiter->Status.FiredEvent = info->WaitIndex; + // memory_order_relaxed: The flip to false is only lazily observed as an + // optimization to bypass the mutex for cleanup. + info->Waiter->StillWaiting.store(false, std::memory_order_relaxed); + } + + result = pthread_mutex_unlock(&info->Waiter->Mutex); + assert(result == 0); + + result = pthread_cond_signal(&info->Waiter->CVariable); + assert(result == 0); + + // memory_order_seq_cst: Ensure this is run after the wfmo mutex is unlocked + int ref_count = info->Waiter->RefCount.fetch_sub(1, std::memory_order_seq_cst); + assert(ref_count > 0); + if (ref_count == 1) { + info->Waiter->Destroy(); + delete info->Waiter; + } + continue; + } + event->RegisteredWaits.clear(); +#endif // WFMO + result = pthread_mutex_unlock(&event->Mutex); + assert(result == 0); + + result = pthread_cond_broadcast(&event->CVariable); + assert(result == 0); + } + + return 0; + } + + int ResetEvent(neosmart_event_t event) { + // memory_order_relaxed and no mutex: there can't be any guarantees about concurrent calls + // to either of WFMO()/SetEvent() and ResetEvent() because they're racy by nature. Only the + // behavior of concurrent WFMO() and SetEvent() calls is strongly defined. + event->State.store(false, std::memory_order_relaxed); + return 0; + } + +#ifdef PULSE + int PulseEvent(neosmart_event_t event) { + // This may look like it's a horribly inefficient kludge with the sole intention of reducing + // code duplication, but in reality this is what any PulseEvent() implementation must look + // like. The only overhead (function calls aside, which your compiler will likely optimize + // away, anyway), is if only WFMO auto-reset waits are active there will be overhead to + // unnecessarily obtain the event mutex for ResetEvent() after. In all other cases (being no + // pending waits, WFMO manual-reset waits, or any WFSO waits), the event mutex must first be + // released for the waiting thread to resume action prior to locking the mutex again in + // order to set the event state to unsignaled, or else the waiting threads will loop back + // into a wait (due to checks for spurious CVariable wakeups). + + int result = SetEvent(event); + assert(result == 0); + result = ResetEvent(event); + assert(result == 0); + + return 0; + } +#endif +} // namespace neosmart + +#else // _WIN32 + +#include +#include "pevents.h" + +namespace neosmart { + neosmart_event_t CreateEvent(bool manualReset, bool initialState) { + return static_cast(::CreateEvent(NULL, manualReset, initialState, NULL)); + } + + int DestroyEvent(neosmart_event_t event) { + HANDLE handle = static_cast(event); + return CloseHandle(handle) ? 0 : GetLastError(); + } + + int WaitForEvent(neosmart_event_t event, uint64_t milliseconds) { + uint32_t result = 0; + HANDLE handle = static_cast(event); + + // WaitForSingleObject(Ex) and WaitForMultipleObjects(Ex) only support 32-bit timeout + if (milliseconds == WAIT_INFINITE || (milliseconds >> 32) == 0) { + result = WaitForSingleObject(handle, static_cast(milliseconds)); + } else { + // Cannot wait for 0xFFFFFFFF because that means infinity to WIN32 + uint32_t waitUnit = static_cast(WAIT_INFINITE) - 1; + uint64_t rounds = milliseconds / waitUnit; + uint32_t remainder = milliseconds % waitUnit; + + result = WaitForSingleObject(handle, remainder); + while (result == WAIT_TIMEOUT && rounds-- != 0) { + result = WaitForSingleObject(handle, waitUnit); + } + } + + if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) { + // We must swallow WAIT_ABANDONED because there is no such equivalent on *nix + return 0; + } + + if (result == WAIT_TIMEOUT) { + return WAIT_TIMEOUT; + } + + return GetLastError(); + } + + int SetEvent(neosmart_event_t event) { + HANDLE handle = static_cast(event); + return ::SetEvent(handle) ? 0 : GetLastError(); + } + + int ResetEvent(neosmart_event_t event) { + HANDLE handle = static_cast(event); + return ::ResetEvent(handle) ? 0 : GetLastError(); + } + +#ifdef WFMO + int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, + uint64_t milliseconds) { + int index = 0; + return WaitForMultipleEvents(events, count, waitAll, milliseconds, index); + } + + int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, + uint64_t milliseconds, int &index) { + HANDLE *handles = reinterpret_cast(events); + uint32_t result = 0; + + // WaitForSingleObject(Ex) and WaitForMultipleObjects(Ex) only support 32-bit timeout + if (milliseconds == WAIT_INFINITE || (milliseconds >> 32) == 0) { + result = WaitForMultipleObjects(count, handles, waitAll, + static_cast(milliseconds)); + } else { + // Cannot wait for 0xFFFFFFFF because that means infinity to WIN32 + uint32_t waitUnit = static_cast(WAIT_INFINITE) - 1; + uint64_t rounds = milliseconds / waitUnit; + uint32_t remainder = milliseconds % waitUnit; + + result = WaitForMultipleObjects(count, handles, waitAll, remainder); + while (result == WAIT_TIMEOUT && rounds-- != 0) { + result = WaitForMultipleObjects(count, handles, waitAll, waitUnit); + } + } + + if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + count) { + index = result - WAIT_OBJECT_0; + return 0; + } else if (result >= WAIT_ABANDONED_0 && result < WAIT_ABANDONED_0 + count) { + index = result - WAIT_ABANDONED_0; + return 0; + } + + if (result == WAIT_FAILED) { + return GetLastError(); + } + return result; + } +#endif + +#ifdef PULSE + int PulseEvent(neosmart_event_t event) { + HANDLE handle = static_cast(event); + return ::PulseEvent(handle) ? 0 : GetLastError(); + } +#endif +} // namespace neosmart + +#endif //_WIN32 diff --git a/source/third_party/pevents/src/pevents.h b/source/third_party/pevents/src/pevents.h new file mode 100644 index 0000000..857fe19 --- /dev/null +++ b/source/third_party/pevents/src/pevents.h @@ -0,0 +1,43 @@ +/* + * WIN32 Events for POSIX + * Author: Mahmoud Al-Qudsi + * Copyright (C) 2011 - 2022 by NeoSmart Technologies + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#if defined(_WIN32) && !defined(CreateEvent) +#error Must include Windows.h prior to including pevents.h! +#endif +#ifndef WAIT_TIMEOUT +#include +#define WAIT_TIMEOUT ETIMEDOUT +#endif + +#include + +namespace neosmart { + // Type declarations + struct neosmart_event_t_; + typedef neosmart_event_t_ *neosmart_event_t; + + // Constant declarations + const uint64_t WAIT_INFINITE = ~((uint64_t)0); + + // Function declarations + neosmart_event_t CreateEvent(bool manualReset = false, bool initialState = false); + int DestroyEvent(neosmart_event_t event); + int WaitForEvent(neosmart_event_t event, uint64_t milliseconds = WAIT_INFINITE); + int SetEvent(neosmart_event_t event); + int ResetEvent(neosmart_event_t event); +#ifdef WFMO + int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, + uint64_t milliseconds); + int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, + uint64_t milliseconds, int &index); +#endif +#ifdef PULSE + int PulseEvent(neosmart_event_t event); +#endif +} // namespace neosmart diff --git a/source/third_party/pevents/win32.cpp b/source/third_party/pevents/win32.cpp deleted file mode 100644 index b8c786e..0000000 --- a/source/third_party/pevents/win32.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * WIN32 Events for POSIX - * Author: Mahmoud Al-Qudsi - * Copyright (C) 2011 - 2015 by NeoSmart Technologies - * This code is released under the terms of the MIT License -*/ - -#ifdef _WIN32 - -#include -#include "pevents.h" - -namespace neosmart -{ - neosmart_event_t CreateEvent(bool manualReset, bool initialState) - { - return static_cast(::CreateEvent(NULL, manualReset, initialState, NULL)); - } - - int DestroyEvent(neosmart_event_t event) - { - HANDLE handle = static_cast(event); - return CloseHandle(handle) ? 0 : GetLastError(); - } - - int WaitForEvent(neosmart_event_t event, uint64_t milliseconds) - { - uint32_t result = 0; - HANDLE handle = static_cast(event); - - //WaitForSingleObject(Ex) and WaitForMultipleObjects(Ex) only support 32-bit timeout - if (milliseconds == ((uint64_t) -1) || (milliseconds >> 32) == 0) - { - result = WaitForSingleObject(handle, static_cast(milliseconds)); - } - else - { - //Cannot wait for 0xFFFFFFFF because that means infinity to WIN32 - uint32_t waitUnit = (INFINITE - 1); - uint64_t rounds = milliseconds / waitUnit; - uint32_t remainder = milliseconds % waitUnit; - - uint32_t result = WaitForSingleObject(handle, remainder); - while (result == WAIT_TIMEOUT && rounds-- != 0) - { - result = WaitForSingleObject(handle, waitUnit); - } - } - - if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) - { - //We must swallow WAIT_ABANDONED because there is no such equivalent on *nix - return 0; - } - - if (result == WAIT_TIMEOUT) - { - return WAIT_TIMEOUT; - } - - return GetLastError(); - } - - int SetEvent(neosmart_event_t event) - { - HANDLE handle = static_cast(event); - return ::SetEvent(handle) ? 0 : GetLastError(); - } - - int ResetEvent(neosmart_event_t event) - { - HANDLE handle = static_cast(event); - return ::ResetEvent(handle) ? 0 : GetLastError(); - } - -#ifdef WFMO - int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds) - { - int index = 0; - return WaitForMultipleEvents(events, count, waitAll, milliseconds, index); - } - - int WaitForMultipleEvents(neosmart_event_t *events, int count, bool waitAll, uint64_t milliseconds, int &index) - { - HANDLE *handles = reinterpret_cast(events); - uint32_t result = 0; - - //WaitForSingleObject(Ex) and WaitForMultipleObjects(Ex) only support 32-bit timeout - if (milliseconds == ((uint64_t) -1) || (milliseconds >> 32) == 0) - { - result = WaitForMultipleObjects(count, handles, waitAll, static_cast(milliseconds)); - } - else - { - //Cannot wait for 0xFFFFFFFF because that means infinity to WIN32 - uint32_t waitUnit = (INFINITE - 1); - uint64_t rounds = milliseconds / waitUnit; - uint32_t remainder = milliseconds % waitUnit; - - uint32_t result = WaitForMultipleObjects(count, handles, waitAll, remainder); - while (result == WAIT_TIMEOUT && rounds-- != 0) - { - result = WaitForMultipleObjects(count, handles, waitAll, waitUnit); - } - } - - if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + count) - { - index = result - WAIT_OBJECT_0; - return 0; - } - else if (result >= WAIT_ABANDONED_0 && result < WAIT_ABANDONED_0 + count) - { - index = result - WAIT_ABANDONED_0; - return 0; - } - - if (result == WAIT_FAILED) - { - return GetLastError(); - } - return result; - } -#endif - -#ifdef PULSE - int PulseEvent(neosmart_event_t event) - { - HANDLE handle = static_cast(event); - return ::PulseEvent(handle) ? 0 : GetLastError(); - } -#endif -} - -#endif //_WIN32