Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ This can be installed once Python is installed, as follows:
Run the python pre_build.py script in the build folder from a command prompt. If no command line options are provided, the defaults will be used (Qt 6.7.0 and Visual Studio 2022)

Some useful options of the pre_build.py script:
* --vs <Visual Studio version>: generate the solution files for a specific Visual Studio version. For example, to target Visual Studio 2017, add --vs 2017 to the command.
* --qt <path>: full path to the folder from where you would like the Qt binaries to be retrieved. By default, CMake would try to auto-detect Qt on the system.
* --vs \<Visual Studio version\>: generate the solution files for a specific Visual Studio version. For example, to target Visual Studio 2017, add --vs 2017 to the command.
* --qt \<QT Version\>: specify the version of QT to be used with the script (default: 6.7.0).
* --qt-root \<path\>: full path to the folder from where you would like the Qt binaries to be retrieved. By default, CMake would try to auto-detect Qt on the system.

Once the script has finished, in the case of Visual Studio 2019, a sub-folder called 'vs2019' will be created containing the necessary build files.
Go into the 'vs2019' folder (build/win/vs2019) and double click on the RMV.sln file and build the 64-bit Debug and Release builds.
Expand Down
15 changes: 15 additions & 0 deletions source/frontend/models/compare/memory_leak_finder_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,31 @@ namespace rmv
UpdateLabels();
}

void MemoryLeakFinderModel::FilterByMipLevelChanged(int min_value, int max_value)
{
const uint64_t scaled_min = rmv_util::CalculateThresholdFromStepValue(min_value, rmv::kMipSliderRange - 1);
const uint64_t scaled_max = rmv_util::CalculateThresholdFromStepValue(max_value, rmv::kMipSliderRange - 1);

proxy_model_->SetMipLevelFilter(scaled_min, scaled_max);
proxy_model_->invalidate();

UpdateLabels();
}

void MemoryLeakFinderModel::UpdatePreferredHeapList(const QString& preferred_heap_filter)
{
proxy_model_->SetPreferredHeapFilter(preferred_heap_filter);
proxy_model_->invalidate();

UpdateLabels();
}

void MemoryLeakFinderModel::UpdateResourceUsageList(const QString& resource_usage_filter)
{
proxy_model_->SetResourceUsageFilter(resource_usage_filter);
proxy_model_->invalidate();

UpdateLabels();
}

MemoryLeakFinderProxyModel* MemoryLeakFinderModel::GetResourceProxyModel() const
Expand Down
6 changes: 6 additions & 0 deletions source/frontend/models/compare/memory_leak_finder_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ namespace rmv
/// @param [in] max_value Maximum value of slider span.
void FilterBySizeChanged(int min_value, int max_value);

/// @brief Handle what happens when user changes the 'filter by mip level' slider.
///
/// @param [in] min_value Minimum value of slider span.
/// @param [in] max_value Maximum value of slider span.
void FilterByMipLevelChanged(int min_value, int max_value);

/// @brief Update the list of heaps selected. This is set up from the preferred heap combo box.
///
/// @param [in] preferred_heap_filter The regular expression string of selected heaps.
Expand Down
54 changes: 52 additions & 2 deletions source/frontend/models/proxy_models/resource_proxy_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,16 @@ namespace rmv
setSourceModel(model);
SetFilterKeyColumns({kResourceColumnName,
kResourceColumnVirtualAddress,
kResourceColumnUsage,
kResourceColumnDimension,
kResourceColumnMipLevel,
kResourceColumnFormat,
kResourceColumnSize,
kResourceColumnMappedInvisible,
kResourceColumnMappedLocal,
kResourceColumnMappedHost,
kResourceColumnMappedNone,
kResourceColumnPreferredHeap,
kResourceColumnUsage});
kResourceColumnPreferredHeap});

view->setModel(this);
return model;
Expand All @@ -63,6 +66,11 @@ namespace rmv
return false;
}

if (FilterMipLevelSlider(source_row, kResourceColumnMipLevel, source_parent) == false)
{
return false;
}

// Apply the range-based searching to the virtual address and resource size.
// Only fail if the search string is outside the address range.
bool found_range = false;
Expand Down Expand Up @@ -161,6 +169,48 @@ namespace rmv
}
return left_data < right_data;
}
else if ((left.column() == kResourceColumnDimension && right.column() == kResourceColumnDimension))
{
const QList<QVariant> left_data = left.data(Qt::UserRole).toList();
const QList<QVariant> right_data = right.data(Qt::UserRole).toList();
if (left_data == right_data)
{
return SortIdentical(left, right);
}

qlonglong left_pixels = 1;
qlonglong right_pixels = 1;
for (const QVariant& data : left_data)
{
left_pixels *= data.toInt();
}
for (const QVariant& data : right_data)
{
right_pixels *= data.toInt();
}

return left_pixels < right_pixels;
}
else if ((left.column() == kResourceColumnMipLevel && right.column() == kResourceColumnMipLevel))
{
const int left_data = left.data(Qt::UserRole).toInt();
const int right_data = right.data(Qt::UserRole).toInt();
if (left_data == right_data)
{
return SortIdentical(left, right);
}
return left_data < right_data;
}
else if ((left.column() == kResourceColumnFormat && right.column() == kResourceColumnFormat))
{
const QString left_data = left.data(Qt::UserRole).toString();
const QString right_data = right.data(Qt::UserRole).toString();
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();
Expand Down
29 changes: 29 additions & 0 deletions source/frontend/models/proxy_models/table_proxy_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace rmv
: QSortFilterProxyModel(parent)
, min_size_(0)
, max_size_(UINT64_MAX)
, min_mip_level_(1)
, max_mip_level_(UINT64_MAX)
{
}

Expand Down Expand Up @@ -42,6 +44,12 @@ namespace rmv
max_size_ = max;
}

void TableProxyModel::SetMipLevelFilter(uint64_t min, uint64_t max)
{
min_mip_level_ = min;
max_mip_level_ = max;
}

uint64_t TableProxyModel::GetIndexValue(const QModelIndex& index) const
{
const QString data = sourceModel()->data(index).toString();
Expand All @@ -62,6 +70,19 @@ namespace rmv
return out;
}

QString TableProxyModel::GetDataAsStr(int row, int column)
{
QString out("null");

const QModelIndex model_index = index(row, column, QModelIndex());

if (model_index.isValid() == true)
{
out = data(model_index, Qt::DisplayRole).toString();
}
return out;
}

QModelIndex TableProxyModel::FindModelIndex(qulonglong lookup, int column) const
{
QModelIndex out_model_index;
Expand Down Expand Up @@ -95,6 +116,14 @@ namespace rmv
return !(size < min_size_ || size > max_size_);
}

bool TableProxyModel::FilterMipLevelSlider(int row, int column, const QModelIndex& source_parent) const
{
const QModelIndex& mip_filter_index = sourceModel()->index(row, column, source_parent);
const uint32_t mip_level = mip_filter_index.data(Qt::UserRole).toUInt();

return mip_level == 0 || !(mip_level < min_mip_level_ || mip_level > max_mip_level_);
}

bool TableProxyModel::FilterSearchString(int row, const QModelIndex& source_parent) const
{
if (column_filters_.empty() == false && search_filter_.isEmpty() == false)
Expand Down
25 changes: 25 additions & 0 deletions source/frontend/models/proxy_models/table_proxy_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ namespace rmv
/// @param [in] max The maximum size.
void SetSizeFilter(uint64_t min, uint64_t max);

/// @brief Specify range to use as mip level filter.
///
/// @param [in] min The minimum mip level.
/// @param [in] max The maximum mip level.
void SetMipLevelFilter(uint64_t min, uint64_t max);

/// @brief Get content from proxy model.
///
/// @param [in] row The row where the data is located.
Expand All @@ -52,6 +58,14 @@ namespace rmv
/// @return The contents at row, column.
qulonglong GetData(int row, int column);

/// @brief Get content from proxy model.
///
/// @param [in] row The row where the data is located.
/// @param [in] column The column where the data is located.
///
/// @return The string contents at row, column.
QString GetDataAsStr(int row, int column);

/// @brief Find a model index corresponding to the passed in data.
///
/// @param [in] lookup The value to find.
Expand Down Expand Up @@ -90,6 +104,15 @@ namespace rmv
/// @return true if the table item at row,column is to be shown, false if not.
bool FilterSizeSlider(int row, int column, const QModelIndex& source_parent) const;

/// @brief Filter the mip level slider.
///
/// @param [in] row The row to apply the mip level filter to.
/// @param [in] column The column to apply the mip level filter to.
/// @param [in] source_parent The parent model index in the source model.
///
/// @return true if the table item at row,column is to be shown, false if not.
bool FilterMipLevelSlider(int row, int column, const QModelIndex& source_parent) const;

/// @brief Filter the search string.
///
/// @param [in] row The row to apply the size filter to.
Expand All @@ -109,6 +132,8 @@ namespace rmv
QString search_filter_; ///< The current search string.
uint64_t min_size_; ///< The minimum size of the size filter.
uint64_t max_size_; ///< The maximum size of the size filter.
uint64_t min_mip_level_; ///< The minimum size of the mip level filter.
uint64_t max_mip_level_; ///< The maximum size of the mip level filter.
};
} // namespace rmv

Expand Down
45 changes: 45 additions & 0 deletions source/frontend/models/resource_item_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ namespace rmv
resource_table->SetColumnWidthEms(kResourceColumnCompareId, 8);
resource_table->SetColumnWidthEms(kResourceColumnName, 20);
resource_table->SetColumnWidthEms(kResourceColumnVirtualAddress, 11);
resource_table->SetColumnWidthEms(kResourceColumnDimension, 11);
resource_table->SetColumnWidthEms(kResourceColumnMipLevel, 6);
resource_table->SetColumnWidthEms(kResourceColumnFormat, 8);
resource_table->SetColumnWidthEms(kResourceColumnSize, 8);
resource_table->SetColumnWidthEms(kResourceColumnPreferredHeap, 11);
resource_table->SetColumnWidthEms(kResourceColumnMappedInvisible, 13);
Expand Down Expand Up @@ -134,6 +137,18 @@ namespace rmv
return cache_[row].resource_name;
case kResourceColumnVirtualAddress:
return rmv::string_util::LocalizedValueAddress(RmtResourceGetVirtualAddress(resource));
case kResourceColumnDimension:
return resource->resource_type == kRmtResourceTypeImage
? QString::asprintf("%dx%dx%d", resource->image.dimension_x, resource->image.dimension_y, resource->image.dimension_z)
: QString("-");
case kResourceColumnMipLevel:
return resource->resource_type == kRmtResourceTypeImage
? QString::asprintf("%d", resource->image.mip_levels)
: QString("-");
case kResourceColumnFormat:
return resource->resource_type == kRmtResourceTypeImage
? QString(RmtGetFormatNameFromFormat(resource->image.format.format))
: QString("-");
case kResourceColumnSize:
return rmv::string_util::LocalizedValueMemory(resource->size_in_bytes, false, false);
case kResourceColumnMappedInvisible:
Expand Down Expand Up @@ -179,6 +194,18 @@ namespace rmv
return QVariant::fromValue<qulonglong>(resource->identifier);
case kResourceColumnVirtualAddress:
return QVariant::fromValue<qulonglong>(RmtResourceGetVirtualAddress(resource));
case kResourceColumnDimension:
return resource->resource_type == kRmtResourceTypeImage
? QList<QVariant>({resource->image.dimension_x, resource->image.dimension_y, resource->image.dimension_z})
: QList<QVariant>({0, 0, 0});
case kResourceColumnMipLevel:
return resource->resource_type == kRmtResourceTypeImage
? resource->image.mip_levels
: 0;
case kResourceColumnFormat:
return resource->resource_type == kRmtResourceTypeImage
? QString(RmtGetFormatNameFromFormat(resource->image.format.format))
: QString("-");
case kResourceColumnSize:
return QVariant::fromValue<qulonglong>(resource->size_in_bytes);
case kResourceColumnMappedInvisible:
Expand Down Expand Up @@ -207,6 +234,18 @@ namespace rmv
{
case kResourceColumnName:
return cache_[row].resource_name;
case kResourceColumnDimension:
return resource->resource_type == kRmtResourceTypeImage
? QString::asprintf("%dx%dx%d", resource->image.dimension_x, resource->image.dimension_y, resource->image.dimension_z)
: QString("-");
case kResourceColumnMipLevel:
return resource->resource_type == kRmtResourceTypeImage
? QString::asprintf("%d", resource->image.mip_levels)
: QString("-");
case kResourceColumnFormat:
return resource->resource_type == kRmtResourceTypeImage
? QString(RmtGetFormatNameFromFormat(resource->image.format.format))
: QString("-");
case kResourceColumnSize:
return rmv::string_util::LocalizedValueBytes(resource->size_in_bytes);
case kResourceColumnMappedInvisible:
Expand Down Expand Up @@ -243,6 +282,12 @@ namespace rmv
return "Name";
case kResourceColumnVirtualAddress:
return "Virtual address";
case kResourceColumnDimension:
return "Dimension";
case kResourceColumnMipLevel:
return "Mip Level";
case kResourceColumnFormat:
return "Format";
case kResourceColumnSize:
return "Size";
case kResourceColumnPreferredHeap:
Expand Down
5 changes: 4 additions & 1 deletion source/frontend/models/resource_item_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ namespace rmv
kResourceColumnCompareId,
kResourceColumnName,
kResourceColumnVirtualAddress,
kResourceColumnUsage,
kResourceColumnDimension,
kResourceColumnMipLevel,
kResourceColumnFormat,
kResourceColumnSize,
kResourceColumnPreferredHeap,
kResourceColumnMappedInvisible,
kResourceColumnMappedLocal,
kResourceColumnMappedHost,
kResourceColumnMappedNone,
kResourceColumnUsage,

// Hidden, these columns are used as proxies for sorting by other columns.
kResourceColumnAllocationIdInternal,
Expand Down
11 changes: 11 additions & 0 deletions source/frontend/models/snapshot/resource_list_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ namespace rmv
UpdateBottomLabels();
}

void ResourceListModel::FilterByMipLevelChanged(int min_value, int max_value)
{
const uint64_t scaled_min = rmv_util::CalculateThresholdFromStepValue(min_value, rmv::kMipSliderRange - 1);
const uint64_t scaled_max = rmv_util::CalculateThresholdFromStepValue(max_value, rmv::kMipSliderRange - 1);

proxy_model_->SetMipLevelFilter(scaled_min, scaled_max);
proxy_model_->invalidate();

UpdateBottomLabels();
}

ResourceProxyModel* ResourceListModel::GetResourceProxyModel() const
{
return proxy_model_;
Expand Down
6 changes: 6 additions & 0 deletions source/frontend/models/snapshot/resource_list_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ namespace rmv
/// @param [in] max_value Maximum value of slider span.
void FilterBySizeChanged(int min_value, int max_value);

/// @brief Handle what happens when the mip level filter changes.
///
/// @param [in] min_value Minimum value of slider span.
/// @param [in] max_value Maximum value of slider span.
void FilterByMipLevelChanged(int min_value, int max_value);

/// @brief Read the dataset and update model.
void Update();

Expand Down
Loading