This commit is contained in:
xsl
2025-09-04 10:54:47 +08:00
commit 6bc8f61b18
1808 changed files with 208268 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
#[[
Copyright (c) 2019-2023, Arm Limited and Contributors
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 the "License";
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]
cmake_minimum_required(VERSION 3.16)
# Snake case to Pascal case helper
function(snake_case_to_pascal_case SNAKE PASCAL)
set(SNAKE_CASE ${SNAKE})
string(LENGTH "${SNAKE_CASE}" LEN)
string(REGEX MATCH "(^.)" FIRST_LETTER "${SNAKE_CASE}")
string(TOUPPER "${FIRST_LETTER}" FIRST_LETTER)
string(SUBSTRING "${SNAKE_CASE}" 1 ${LEN} REST)
set(SNAKE_CASE "${FIRST_LETTER}${REST}")
string(REGEX MATCH "_([a-zA-Z])[^_]+" HAS_UNDER_SCORES "${SNAKE_CASE}")
if(HAS_UNDER_SCORES)
while(true)
string(REGEX MATCH "_([a-zA-Z])" NEXT "${SNAKE_CASE}")
if(NEXT)
string(SUBSTRING "${NEXT}" 1 1 FIRST_LETTER)
string(TOUPPER "${FIRST_LETTER}" FIRST_LETTER)
string(REGEX REPLACE "${NEXT}" "${FIRST_LETTER}" SNAKE_CASE "${SNAKE_CASE}")
else()
break()
endif()
endwhile()
endif()
set(${PASCAL} ${SNAKE_CASE} PARENT_SCOPE)
endfunction()
# Plugins
file(GLOB PLUGINS_FILES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*")
set(PLUGINS)
foreach(DIR IN LISTS PLUGINS_FILES)
if (IS_DIRECTORY ${DIR})
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" PLUGIN ${DIR})
list(APPEND PLUGINS "${PLUGIN}")
endif()
endforeach()
# filter compiled plugins
if(NOT ${VKB_BUILD_TESTS})
list(REMOVE_ITEM PLUGINS "start_test")
endif()
# Generate plugins.cpp
set(PLUGIN_INCLUDE_FILES)
set(INIT_PLUGINS)
foreach(EXT_SNAKE IN LISTS PLUGINS)
message("-- Plugin `${EXT_SNAKE}` - BUILD")
snake_case_to_pascal_case("${EXT_SNAKE}" EXT_PASCAL)
list(APPEND PLUGIN_INCLUDE_FILES "#include \"${EXT_SNAKE}/${EXT_SNAKE}.h\"")
list(APPEND INIT_PLUGINS "\t\tADD_PLUGIN(${EXT_PASCAL})")
endforeach()
list(JOIN PLUGIN_INCLUDE_FILES "\n" PLUGIN_INCLUDE_FILES)
list(JOIN INIT_PLUGINS ";\n" INIT_PLUGINS)
set(INIT_PLUGINS "${INIT_PLUGINS};")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/plugins.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/plugins.cpp)
# Create plugins library
set(SRC_FILES
${CMAKE_CURRENT_BINARY_DIR}/plugins.cpp
plugins.h
)
foreach(PLUGIN IN LISTS PLUGINS)
list(APPEND SRC_FILES "${PLUGIN}/${PLUGIN}.h")
list(APPEND SRC_FILES "${PLUGIN}/${PLUGIN}.cpp")
endforeach()
add_library(plugins OBJECT ${SRC_FILES})
target_include_directories(plugins PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} $<TARGET_PROPERTY:apps,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:framework,INTERFACE_INCLUDE_DIRECTORIES>)
target_compile_options(plugins PRIVATE $<TARGET_PROPERTY:apps,INTERFACE_COMPILE_OPTIONS> $<TARGET_PROPERTY:framework,INTERFACE_COMPILE_OPTIONS>)
target_compile_features(plugins PRIVATE $<TARGET_PROPERTY:apps,INTERFACE_COMPILE_FEATURES> $<TARGET_PROPERTY:framework,INTERFACE_COMPILE_FEATURES>)
target_compile_definitions(plugins PRIVATE $<TARGET_PROPERTY:apps,INTERFACE_COMPILE_DEFINITIONS> $<TARGET_PROPERTY:framework,INTERFACE_COMPILE_DEFINITIONS>)
+232
View File
@@ -0,0 +1,232 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "batch_mode.h"
#include "vulkan_sample.h"
namespace plugins
{
BatchMode::BatchMode() :
BatchModeTags("Batch Mode",
"Run a collection of samples in sequence.",
{
vkb::Hook::OnUpdate,
vkb::Hook::OnAppError,
},
{{"batch", "Enable batch mode"}},
{{"category", "Filter samples by categories"},
{"duration", "The duration which a configuration should run for in seconds"},
{"skip", "Skip a sample by id"},
{"tag", "Filter samples by tags"},
{"wrap-to-start", "Once all configurations have run wrap to the start"}})
{
}
bool BatchMode::handle_command(std::deque<std::string> &arguments) const
{
assert(!arguments.empty());
if (arguments[0] == "batch")
{
arguments.pop_front();
return true;
}
return false;
}
bool BatchMode::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "category")
{
if (arguments.size() < 2)
{
LOGE("Option \"category\" is missing the actual category!");
return false;
}
std::string category = arguments[1];
if (std::ranges::any_of(categories, [&category](auto const &c) { return c == category; }))
{
LOGW("Option \"category\" lists category \"{}\" multiple times!", category)
}
else
{
categories.push_back(category);
}
arguments.pop_front();
arguments.pop_front();
return true;
}
else if (option == "duration")
{
if (arguments.size() < 2)
{
LOGE("Option \"duration\" is missing the actual duration!");
return false;
}
duration = std::chrono::duration<float, vkb::Timer::Seconds>{std::stof(arguments[1])};
arguments.pop_front();
arguments.pop_front();
return true;
}
else if (option == "skip")
{
if (arguments.size() < 2)
{
LOGE("Option \"skip\" is missing the sample_id to skip!");
return false;
}
std::string sample_id = arguments[1];
if (!skips.insert(sample_id).second)
{
LOGW("Option \"skip\" lists sample_id \"{}\" multiple times!", sample_id)
}
arguments.pop_front();
arguments.pop_front();
return true;
}
else if (option == "tag")
{
if (arguments.size() < 2)
{
LOGE("Option \"tag\" is missing the actual to tag!");
return false;
}
std::string tag = arguments[1];
if (std::ranges::any_of(tags, [&tag](auto const &t) { return t == tag; }))
{
LOGW("Option \"tag\" lists tag \"{}\" multiple times!", tag)
}
else
{
tags.push_back(tag);
}
arguments.pop_front();
arguments.pop_front();
return true;
}
else if (option == "wrap-to-start")
{
wrap_to_start = true;
arguments.pop_front();
return true;
}
return false;
}
void BatchMode::trigger_command()
{
sample_list = apps::get_samples(categories, tags);
if (!skips.empty())
{
std::vector<apps::AppInfo *> filtered_list;
filtered_list.reserve(sample_list.size() - skips.size());
std::copy_if(
sample_list.begin(), sample_list.end(), std::back_inserter(filtered_list), [&](const apps::AppInfo *app) { return !skips.count(app->id); });
if (filtered_list.size() != sample_list.size())
{
sample_list.swap(filtered_list);
}
}
if (sample_list.empty())
{
LOGE("No samples found")
throw std::runtime_error{"Can not continue"};
}
sample_iter = sample_list.begin();
vkb::Window::OptionalProperties properties;
properties.resizable = false;
platform->set_window_properties(properties);
platform->disable_input_processing();
platform->force_render(true);
request_app();
}
void BatchMode::on_update(float delta_time)
{
elapsed_time += delta_time;
// When the runtime for the current configuration is reached, advance to the next config or next sample
if (elapsed_time >= duration.count())
{
elapsed_time = 0.0f;
// Only check and advance the config if the application is a vulkan sample
if (auto *vulkan_app = dynamic_cast<vkb::VulkanSampleC *>(&platform->get_app()))
{
auto &configuration = vulkan_app->get_configuration();
if (configuration.next())
{
configuration.set();
return;
}
}
// Cycled through all configs, load next app
load_next_app();
}
}
void BatchMode::on_app_error(const std::string &app_id)
{
// App failed, load next app
load_next_app();
}
void BatchMode::request_app()
{
LOGI("===========================================");
LOGI("Running {}", (*sample_iter)->id);
LOGI("===========================================");
platform->request_application((*sample_iter));
}
void BatchMode::load_next_app()
{
// Wrap it around to the start
++sample_iter;
if (sample_iter == sample_list.end())
{
if (wrap_to_start)
{
sample_iter = sample_list.begin();
}
else
{
platform->close();
return;
}
}
// App will be started before the next update loop
request_app();
}
} // namespace plugins
+70
View File
@@ -0,0 +1,70 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <chrono>
#include <vector>
#include "apps.h"
#include "platform/plugins/plugin_base.h"
#include "timer.h"
using namespace std::chrono_literals;
namespace plugins
{
using BatchModeTags = vkb::PluginBase<vkb::tags::Entrypoint, vkb::tags::FullControl>;
/**
* @brief Batch Mode
*
* Run a subset of samples. The next sample in the set will start after the current sample being executed has finished. Using --wrap-to-start will start again from the first sample after the last sample is executed.
*
* Usage: vulkan_samples batch --duration 3 --category performance --tag arm
*
*/
class BatchMode : public BatchModeTags
{
public:
BatchMode();
virtual ~BatchMode() = default;
void on_update(float delta_time) override;
void on_app_error(const std::string &app_id) override;
bool handle_command(std::deque<std::string> &arguments) const override;
bool handle_option(std::deque<std::string> &arguments) override;
void trigger_command() override;
private:
void request_app();
void load_next_app();
private:
std::vector<std::string> categories;
std::chrono::duration<float, vkb::Timer::Seconds> duration = 3s;
float elapsed_time = 0.0f;
std::set<std::string> skips;
std::vector<apps::AppInfo *>::const_iterator sample_iter; // An iterator to the current batch mode sample info object
std::vector<apps::AppInfo *> sample_list; // The list of suitable samples to be run in conjunction with batch mode
std::vector<std::string> tags;
bool wrap_to_start = false;
};
} // namespace plugins
@@ -0,0 +1,68 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "benchmark_mode.h"
#include "platform/platform.h"
namespace plugins
{
BenchmarkMode::BenchmarkMode() :
BenchmarkModeTags("Benchmark Mode",
"Log frame averages after running an app.",
{vkb::Hook::OnUpdate, vkb::Hook::OnAppStart, vkb::Hook::OnAppClose},
{},
{{"benchmark", "Enable benchmark mode"}})
{
}
bool BenchmarkMode::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "benchmark")
{
// Whilst in benchmark mode fix the fps so that separate runs are consistently simulated
// This will effect the graph outputs of framerate
platform->force_simulation_fps(60.0f);
platform->force_render(true);
arguments.pop_front();
return true;
}
return false;
}
void BenchmarkMode::on_update(float delta_time)
{
elapsed_time += delta_time;
total_frames++;
}
void BenchmarkMode::on_app_start(const std::string &app_id)
{
elapsed_time = 0;
total_frames = 0;
LOGI("Starting Benchmark for {}", app_id);
}
void BenchmarkMode::on_app_close(const std::string &app_id)
{
LOGI("Benchmark for {} completed in {} seconds (ran {} frames, averaged {} fps)", app_id, elapsed_time, total_frames, total_frames / elapsed_time);
}
} // namespace plugins
@@ -0,0 +1,54 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
class BenchmarkMode;
using BenchmarkModeTags = vkb::PluginBase<BenchmarkMode, vkb::tags::Passive>;
/**
* @brief Benchmark Mode
*
* When enabled frame time statistics of a samples run will be printed to the console when an application closes. The simulation frame time (delta time) is also locked to 60FPS so that statistics can be compared more accurately across different devices.
*
* Usage: vulkan_samples sample afbc --benchmark
*
*/
class BenchmarkMode : public BenchmarkModeTags
{
public:
BenchmarkMode();
virtual ~BenchmarkMode() = default;
virtual void on_update(float delta_time) override;
virtual void on_app_start(const std::string &app_info) override;
virtual void on_app_close(const std::string &app_info) override;
bool handle_option(std::deque<std::string> &arguments) override;
private:
float elapsed_time = 0.0f;
uint32_t total_frames = 0;
};
} // namespace plugins
+56
View File
@@ -0,0 +1,56 @@
/* Copyright (c) 2022-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "data_path.h"
#include "filesystem/filesystem.hpp"
namespace plugins
{
DataPath::DataPath() :
DataPathTags("Data Path Override",
"Specify the folder containing the sample data folders.",
{vkb::Hook::OnAppStart},
{},
{{"data-path", "Folder containing data files"}})
{
}
bool DataPath::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "data-path")
{
if (arguments.size() < 2)
{
LOGE("Option \"data-path\" is missing the actual data path!");
return false;
}
std::string data_path = arguments[1];
auto fs = vkb::filesystem::get();
fs->set_external_storage_directory(data_path + "/");
arguments.pop_front();
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
+44
View File
@@ -0,0 +1,44 @@
/* Copyright (c) 2022-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
using DataPathTags = vkb::PluginBase<vkb::tags::Passive>;
/**
* @brief Data path override
*
* Controls the root path used to find data files
*
* Usage: vulkan_sample sample afbc --data-path <folder>
*
*/
class DataPath : public DataPathTags
{
public:
DataPath();
virtual ~DataPath() = default;
bool handle_option(std::deque<std::string> &arguments) override;
};
} // namespace plugins
+56
View File
@@ -0,0 +1,56 @@
/* Copyright (c) 2021-2025, Arm Limited and Contributors
* Copyright (c) 2021-2025, Sascha Willems
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "file_logger.h"
#include "apps.h"
#include <fmt/format.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/spdlog.h>
namespace plugins
{
FileLogger::FileLogger() :
FileLoggerTags("File Logger", "Enable log output to a file.", {}, {}, {{"log-file", "Write log messages to the given file name"}})
{
}
bool FileLogger::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "log-file")
{
if (arguments.size() < 2)
{
LOGE("Option \"log-file\" is missing the actual log file name!");
return false;
}
std::string log_file = arguments[1];
spdlog::default_logger()->sinks().push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(log_file, true));
arguments.pop_front();
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
+45
View File
@@ -0,0 +1,45 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2021-2025, Sascha Willems
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
using FileLoggerTags = vkb::PluginBase<vkb::tags::Passive>;
/**
* @brief File Logger
*
* Enables writing log messages to a file
*
* Usage: vulkan_sample --log-file filename.txt
*
*/
class FileLogger : public FileLoggerTags
{
public:
FileLogger();
virtual ~FileLogger() = default;
bool handle_option(std::deque<std::string> &arguments) override;
};
} // namespace plugins
+45
View File
@@ -0,0 +1,45 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "force_close.h"
#include <iostream>
namespace plugins
{
ForceClose::ForceClose() :
ForceCloseTags("Force Close",
"Force the application to close if it has been halted before exiting",
{},
{},
{{"force-close", "Force the close of the application if halted before exiting"}})
{
}
bool ForceClose::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "force-close")
{
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
+49
View File
@@ -0,0 +1,49 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
class ForceClose;
// Passive behaviour
using ForceCloseTags = vkb::PluginBase<ForceClose, vkb::tags::Passive>;
/**
* @brief Force Close
*
* Force the close of the application if halted before exiting
*
* The plugin is used as a boolean with platform->using_plugin<ForceClose>();
*
* Usage: vulkan_sample sample afbc --force-close
*
*/
class ForceClose : public ForceCloseTags
{
public:
ForceClose();
virtual ~ForceClose() = default;
bool handle_option(std::deque<std::string> &arguments) override;
};
} // namespace plugins
+61
View File
@@ -0,0 +1,61 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fps_logger.h"
namespace plugins
{
FpsLogger::FpsLogger() :
FpsLoggerTags("FPS Logger", "Enable FPS logging.", {vkb::Hook::OnUpdate, vkb::Hook::OnAppStart}, {}, {{"log-fps", "Log FPS"}})
{
}
bool FpsLogger::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "log-fps")
{
arguments.pop_front();
return true;
}
return false;
}
void FpsLogger::on_update(float delta_time)
{
if (!timer.is_running())
{
timer.start();
}
auto elapsed_time = static_cast<float>(timer.elapsed<vkb::Timer::Seconds>());
frame_count++;
if (elapsed_time > 0.5f)
{
auto fps = (frame_count - last_frame_count) / elapsed_time;
LOGI("FPS: {:.1f}", fps);
last_frame_count = frame_count;
timer.lap();
}
};
} // namespace plugins
+51
View File
@@ -0,0 +1,51 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
using FpsLoggerTags = vkb::PluginBase<vkb::tags::Passive>;
/**
* @brief FPS Logger
*
* Control when FPS should be logged. Declutters the log output by removing FPS logs when not enabled
*
* Usage: vulkan_sample sample afbc --log-fps
*
*/
class FpsLogger : public FpsLoggerTags
{
public:
FpsLogger();
virtual ~FpsLogger() = default;
void on_update(float delta_time) override;
bool handle_option(std::deque<std::string> &arguments) override;
private:
size_t frame_count = 0;
size_t last_frame_count = 0;
vkb::Timer timer;
};
} // namespace plugins
@@ -0,0 +1,57 @@
/* Copyright (c) 2023-2025, Sascha Willems
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "gpu_selection.h"
#include "core/instance.h"
#include <algorithm>
namespace plugins
{
GpuSelection::GpuSelection() :
GpuSelectionTags("GPU selection",
"A collection of flags to select the GPU to run the samples on",
{},
{},
{{"gpu", "Zero-based index of the GPU that the sample should use"}})
{
}
bool GpuSelection::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "gpu")
{
if (arguments.size() < 2)
{
LOGE("Option \"gpu\" is missing the actual gpu index!");
return false;
}
uint32_t gpu_index = static_cast<uint32_t>(std::stoul(arguments[1]));
vkb::core::InstanceC::selected_gpu_index = gpu_index;
vkb::core::InstanceCpp::selected_gpu_index = gpu_index;
arguments.pop_front();
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
+44
View File
@@ -0,0 +1,44 @@
/* Copyright (c) 2023-2025, Sascha Willems
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
class GpuSelection;
using GpuSelectionTags = vkb::PluginBase<GpuSelection, vkb::tags::Passive>;
/**
* @brief GPU selection options
*
* Explicitly select a GPU to run the samples on
*
*/
class GpuSelection : public GpuSelectionTags
{
public:
GpuSelection();
virtual ~GpuSelection() = default;
bool handle_option(std::deque<std::string> &arguments) override;
};
} // namespace plugins
+52
View File
@@ -0,0 +1,52 @@
/* Copyright (c) 2020-2021, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Generated file by CMake. Don't edit.
#include "plugins.h"
#include <memory>
@PLUGIN_INCLUDE_FILES@
namespace plugins
{
#define ADD_PLUGIN(name) \
plugins.emplace_back(std::make_unique<name>())
std::vector<vkb::Plugin *> get_all()
{
static bool once = true;
static std::vector<std::unique_ptr<vkb::Plugin>> plugins;
if (once) {
once = false;
@INIT_PLUGINS@
}
std::vector<vkb::Plugin *> ptrs;
ptrs.reserve(plugins.size());
for (auto &plugin : plugins)
{
ptrs.push_back(plugin.get());
}
return ptrs;
}
} // namespace plugins
+25
View File
@@ -0,0 +1,25 @@
/* Copyright (c) 2020-2021, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin.h"
namespace plugins
{
extern std::vector<vkb::Plugin *> get_all();
} // namespace plugins
+105
View File
@@ -0,0 +1,105 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "screenshot.h"
#include <chrono>
#include <iomanip>
#include "rendering/render_context.h"
namespace plugins
{
Screenshot::Screenshot() :
ScreenshotTags("Screenshot",
"Save a screenshot of a specific frame",
{vkb::Hook::OnUpdate, vkb::Hook::OnAppStart, vkb::Hook::PostDraw},
{},
{{"screenshot", "Take a screenshot at a given frame"}, {"screenshot-output", "Declare an output name for the image"}})
{
}
bool Screenshot::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "screenshot")
{
if (arguments.size() < 2)
{
LOGE("Option \"screenshot\" is missing the frame index to take a screenshot!");
return false;
}
frame_number = static_cast<uint32_t>(std::stoul(arguments[1]));
arguments.pop_front();
arguments.pop_front();
return true;
}
else if (option == "screenshot-output")
{
if (arguments.size() < 2)
{
LOGE("Option \"screenshot-output\" is missing the filename to store the screenshot!");
return false;
}
output_path = arguments[1];
output_path_set = true;
arguments.pop_front();
arguments.pop_front();
return true;
}
return false;
}
void Screenshot::on_update(float delta_time)
{
current_frame++;
}
void Screenshot::on_app_start(const std::string &name)
{
current_app_name = name;
current_frame = 0;
}
void Screenshot::on_post_draw(vkb::RenderContext &context)
{
if (current_frame == frame_number)
{
if (!output_path_set)
{
// Create generic image path. <app name>-<current timestamp>.png
auto timestamp = std::chrono::system_clock::now();
std::time_t now_tt = std::chrono::system_clock::to_time_t(timestamp);
std::tm tm = *std::localtime(&now_tt);
char buffer[30];
strftime(buffer, sizeof(buffer), "%G-%m-%d---%H-%M-%S", &tm);
std::stringstream stream;
stream << current_app_name << "-" << buffer;
output_path = stream.str();
}
screenshot(context, output_path);
}
}
} // namespace plugins
+59
View File
@@ -0,0 +1,59 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "filesystem/legacy.h"
#include "platform/plugins/plugin_base.h"
namespace plugins
{
class Screenshot;
using ScreenshotTags = vkb::PluginBase<Screenshot, vkb::tags::Passive>;
/**
* @brief Screenshot
*
* Capture a screen shot of the last rendered image at a given frame. The output can also be named
*
* Usage: vulkan_sample sample afbc --screenshot 1 --screenshot-output afbc-screenshot
*
*/
class Screenshot : public ScreenshotTags
{
public:
Screenshot();
virtual ~Screenshot() = default;
void on_update(float delta_time) override;
void on_app_start(const std::string &app_info) override;
void on_post_draw(vkb::RenderContext &context) override;
bool handle_option(std::deque<std::string> &arguments) override;
private:
uint32_t current_frame = 0;
uint32_t frame_number;
std::string current_app_name;
bool output_path_set = false;
std::string output_path;
};
} // namespace plugins
@@ -0,0 +1,77 @@
/* Copyright (c) 2024-2025, Sascha Willems
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "shading_language_selection.h"
#include <algorithm>
#include "platform/application.h"
namespace plugins
{
ShadingLanguageSelection::ShadingLanguageSelection() :
ShadingLanguageSelectionTags("Shading language selection",
"A collection of flags to select shader from different shading languages (glsl, hlsl or slang)",
{},
{},
{{"shading-language", "Shading language to use (glsl, hlsl or slang)"}})
{
}
bool ShadingLanguageSelection::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "shading-language")
{
if (arguments.size() < 2)
{
LOGE("Option \"shading-language\" is missing the actual shading language to use!");
return false;
}
// Make sure it's one of the supported shading languages
std::string shading_language = arguments[1];
std::transform(shading_language.begin(), shading_language.end(), shading_language.begin(), ::tolower);
if (shading_language == "glsl")
{
LOGI("Shading language selection: GLSL");
vkb::Application::set_shading_language(vkb::ShadingLanguage::GLSL);
}
else if (shading_language == "hlsl")
{
LOGI("Shading language selection: HLSL")
vkb::Application::set_shading_language(vkb::ShadingLanguage::HLSL);
}
else if (shading_language == "slang")
{
LOGI("Shading language selection: slang")
vkb::Application::set_shading_language(vkb::ShadingLanguage::SLANG);
}
else
{
LOGE("Invalid shading language selection, defaulting to glsl");
}
arguments.pop_front();
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
@@ -0,0 +1,44 @@
/* Copyright (c) 2024-2025, Sascha Willems
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
class ShadingLanguageSelection;
using ShadingLanguageSelectionTags = vkb::PluginBase<ShadingLanguageSelection, vkb::tags::Passive>;
/**
* @brief Shading language selection options
*
* Select what shading language to run the samples with (glsl, hlsl)
*
*/
class ShadingLanguageSelection : public ShadingLanguageSelectionTags
{
public:
ShadingLanguageSelection();
virtual ~ShadingLanguageSelection() = default;
bool handle_option(std::deque<std::string> &arguments) override;
};
} // namespace plugins
+99
View File
@@ -0,0 +1,99 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "start_sample.h"
#include "apps.h"
namespace plugins
{
StartSample::StartSample() :
StartSampleTags("StartSample",
"A collection of flags to samples and apps.",
{},
{{"sample", "Run a specific sample"},
{"samples", "List available samples with descriptions"},
{"samples-oneline", "List available samples, one per line"}})
{
}
void StartSample::launch_sample(apps::SampleInfo const *sample) const
{
vkb::Window::OptionalProperties properties;
properties.title = "Vulkan Samples: " + sample->name;
platform->set_window_properties(properties);
platform->request_application(sample);
}
void StartSample::list_samples(bool one_per_line) const
{
auto samples = apps::get_samples();
LOGI("");
LOGI("Available Samples");
LOGI("");
for (auto *app : samples)
{
auto sample = reinterpret_cast<apps::SampleInfo *>(app);
if (one_per_line)
{
LOGI("{}", sample->id.c_str());
}
else
{
LOGI("{}", sample->name.c_str());
LOGI("\tid: {}", sample->id.c_str());
LOGI("\tdescription: {}", sample->description.c_str());
LOGI("");
}
}
platform->close();
}
bool StartSample::handle_command(std::deque<std::string> &arguments) const
{
assert(!arguments.empty());
if (arguments[0] == "sample")
{
if (arguments.size() < 2)
{
LOGE("Command \"sample\" is missing the actual sample_id to launch!");
return false;
}
auto *sample = apps::get_sample(arguments[1]);
if (!sample)
{
LOGE("Command \"sample\" is called with an unknown sample_id \"{}\"!", arguments[1]);
return false;
}
launch_sample(sample);
arguments.pop_front();
arguments.pop_front();
return true;
}
if ((arguments[0] == "samples") || (arguments[0] == "samples-oneline"))
{
list_samples(arguments[0] == "samples-oneline");
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
+50
View File
@@ -0,0 +1,50 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/platform.h"
#include "platform/plugins/plugin_base.h"
namespace plugins
{
using StartSampleTags = vkb::PluginBase<vkb::tags::Entrypoint>;
/**
* @brief Start App
*
* Loads a given sample
*
* Usage: vulkan_sample sample afbc
*
* TODO: Could this be extended to allow configuring a sample from the command line? Currently options are set explicitly by the UI
*/
class StartSample : public StartSampleTags
{
public:
StartSample();
virtual ~StartSample() = default;
bool handle_command(std::deque<std::string> &arguments) const override;
private:
void launch_sample(apps::SampleInfo const *sample) const;
void list_samples(bool one_per_line) const;
};
} // namespace plugins
+54
View File
@@ -0,0 +1,54 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "start_test.h"
#include "apps.h"
namespace plugins
{
StartTest::StartTest() :
StartTestTags("Tests", "A collection of flags to run tests.", {}, {{"test", "Run a specific test"}})
{
}
bool StartTest::handle_command(std::deque<std::string> &arguments) const
{
assert(!arguments.empty());
if (arguments[0] == "test")
{
if (arguments.size() < 2)
{
LOGE("Command \"test\" is missing the actual test_id to launch!");
return false;
}
auto *test = apps::get_app(arguments[1]);
if (!test)
{
LOGE("Command \"test\" is called with an unknown test_id \"{}\"!", arguments[1]);
return false;
}
platform->request_application(test);
arguments.pop_front();
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
+44
View File
@@ -0,0 +1,44 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
using StartTestTags = vkb::PluginBase<vkb::tags::Entrypoint>;
/**
* @brief Start Test
*
* Start a given test. Used by system_test.py
*
* Usage: vulkan_sample test bonza
*
*/
class StartTest : public StartTestTags
{
public:
StartTest();
virtual ~StartTest() = default;
bool handle_command(std::deque<std::string> &arguments) const override;
};
} // namespace plugins
+61
View File
@@ -0,0 +1,61 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "stop_after.h"
namespace plugins
{
StopAfter::StopAfter() :
StopAfterTags("Stop After X",
"A collection of flags to stop the running application after a set period.",
{vkb::Hook::OnUpdate},
{},
{{"stop-after-frame", "Stop the application after a certain number of frames"}})
{
}
bool StopAfter::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "stop-after-frame")
{
if (arguments.size() < 2)
{
LOGE("Option \"stop-after-frame\" is missing the actual frame index to stop after!");
return false;
}
remaining_frames = static_cast<uint32_t>(std::stoul(arguments[1]));
arguments.pop_front();
arguments.pop_front();
return true;
}
return false;
}
void StopAfter::on_update(float delta_time)
{
remaining_frames--;
if (remaining_frames <= 0)
{
platform->close();
}
}
} // namespace plugins
+51
View File
@@ -0,0 +1,51 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
using StopAfterTags = vkb::PluginBase<vkb::tags::Stopping>;
/**
* @brief Stop After
*
* Stop the execution of the app after a specific frame.
*
* Usage: vulkan_sample sample afbc --stop-after-frame 100
*
* TODO: Add stop after duration
*
*/
class StopAfter : public StopAfterTags
{
public:
StopAfter();
virtual ~StopAfter() = default;
void on_update(float delta_time) override;
bool handle_option(std::deque<std::string> &arguments) override;
private:
uint32_t remaining_frames{0};
};
} // namespace plugins
@@ -0,0 +1,50 @@
/* Copyright (c) 2023-2025, Sascha Willems
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "user_interface_options.h"
#include <algorithm>
#include "gui.h"
namespace plugins
{
UserInterfaceOptions::UserInterfaceOptions() :
UserInterfaceOptionsTags("User interface options",
"A collection of flags to configure the user interface",
{},
{},
{{"hideui", "If flag is set, hides the user interface at startup"}})
{
}
bool UserInterfaceOptions::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
if (option == "hideui")
{
vkb::GuiC::visible = false;
vkb::GuiCpp::visible = false;
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
@@ -0,0 +1,44 @@
/* Copyright (c) 2023-2025, Sascha Willems
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
class UserInterfaceOptions;
using UserInterfaceOptionsTags = vkb::PluginBase<UserInterfaceOptions, vkb::tags::Passive>;
/**
* @brief User interface Options
*
* Configure the default user interface
*
*/
class UserInterfaceOptions : public UserInterfaceOptionsTags
{
public:
UserInterfaceOptions();
virtual ~UserInterfaceOptions() = default;
bool handle_option(std::deque<std::string> &arguments) override;
};
} // namespace plugins
@@ -0,0 +1,146 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "window_options.h"
#include <algorithm>
#include "platform/platform.h"
#include "platform/window.h"
namespace plugins
{
WindowOptions::WindowOptions() :
WindowOptionsTags("Window Options",
"A collection of flags to configure window used when running the application. Implementation may differ between platforms",
{},
{},
{{"borderless", "Run in borderless mode"},
{"fullscreen", "Run in fullscreen mode"},
{"headless-surface", "Run in headless surface mode. A Surface and swap-chain is still created using VK_EXT_headless_surface."},
{"height", "Initial window height"},
{"stretch", "Stretch window to fullscreen (direct-to-display only)"},
{"vsync", "Force vsync {ON | OFF}. If not set samples decide how vsync is set"},
{"width", "Initial window width"}})
{
}
bool WindowOptions::handle_option(std::deque<std::string> &arguments)
{
assert(!arguments.empty() && (arguments[0].substr(0, 2) == "--"));
std::string option = arguments[0].substr(2);
vkb::Window::OptionalProperties properties;
if (option == "borderless")
{
properties.mode = vkb::Window::Mode::FullscreenBorderless;
platform->set_window_properties(properties);
arguments.pop_front();
return true;
}
else if (option == "fullscreen")
{
properties.mode = vkb::Window::Mode::Fullscreen;
platform->set_window_properties(properties);
arguments.pop_front();
return true;
}
else if (option == "headless-surface")
{
properties.mode = vkb::Window::Mode::Headless;
platform->set_window_properties(properties);
arguments.pop_front();
return true;
}
else if (option == "height")
{
if (arguments.size() < 2)
{
LOGE("Option \"height\" is missing the actual height!");
return false;
}
uint32_t height = static_cast<uint32_t>(std::stoul(arguments[1]));
if (height < platform->MIN_WINDOW_HEIGHT)
{
LOGD("[Window Options] {} is smaller than the minimum height {}, resorting to minimum height", height, platform->MIN_WINDOW_HEIGHT);
height = platform->MIN_WINDOW_HEIGHT;
}
properties.extent.height = height;
platform->set_window_properties(properties);
arguments.pop_front();
arguments.pop_front();
return true;
}
else if (option == "stretch")
{
properties.mode = vkb::Window::Mode::FullscreenStretch;
platform->set_window_properties(properties);
arguments.pop_front();
return true;
}
else if (option == "vsync")
{
if (arguments.size() < 2)
{
LOGE("Option \"vsync\" is missing the actual setting!");
return false;
}
std::string value = arguments[1];
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
if (value == "on")
{
properties.vsync = vkb::Window::Vsync::ON;
}
else if (value == "off")
{
properties.vsync = vkb::Window::Vsync::OFF;
}
platform->set_window_properties(properties);
arguments.pop_front();
arguments.pop_front();
return true;
}
else if (option == "width")
{
if (arguments.size() < 2)
{
LOGE("Option \"width\" is missing the actual width!");
return false;
}
uint32_t width = static_cast<uint32_t>(std::stoul(arguments[1]));
if (width < platform->MIN_WINDOW_WIDTH)
{
LOGD("[Window Options] {} is smaller than the minimum width {}, resorting to minimum width", width, platform->MIN_WINDOW_WIDTH);
width = platform->MIN_WINDOW_WIDTH;
}
properties.extent.width = width;
platform->set_window_properties(properties);
arguments.pop_front();
arguments.pop_front();
return true;
}
return false;
}
} // namespace plugins
@@ -0,0 +1,46 @@
/* Copyright (c) 2020-2025, Arm Limited and Contributors
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "platform/plugins/plugin_base.h"
namespace plugins
{
class WindowOptions;
using WindowOptionsTags = vkb::PluginBase<WindowOptions, vkb::tags::Passive>;
/**
* @brief Window Options
*
* Configure the window used when running Vulkan Samples.
*
* Usage: vulkan_samples sample instancing --width 500 --height 500 --vsync OFF
*
*/
class WindowOptions : public WindowOptionsTags
{
public:
WindowOptions();
virtual ~WindowOptions() = default;
bool handle_option(std::deque<std::string> &arguments) override;
};
} // namespace plugins