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
+141
View File
@@ -0,0 +1,141 @@
# Copyright (c) 2020-2025, Arm Limited and Contributors
# Copyright (c) 2024-2025, Mobica Limited
# Copyright (c) 2024-2025, Sascha Willems
#
# 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.
#
list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/bldsys/cmake/module")
if(NOT DEFINED CMAKE_C_COMPILER_LAUNCHER AND NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER)
find_program(CCACHE_FOUND ccache)
find_program(SCCACHE_FOUND sccache)
if (SCCACHE_FOUND)
message("setting SCCACHE to ${SCCACHE_FOUND}")
set(CMAKE_C_COMPILER_LAUNCHER ${SCCACHE_FOUND})
set(CMAKE_CXX_COMPILER_LAUNCHER ${SCCACHE_FOUND})
elseif(CCACHE_FOUND)
message("setting CCACHE to ${CCACHE_FOUND}")
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_FOUND})
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_FOUND})
endif()
endif()
cmake_minimum_required(VERSION 3.16)
project(vulkan_samples)
if(VKB_GENERATE_ANTORA_SITE)
add_subdirectory(antora)
else ()
# search for Vulkan SDK
find_package(Vulkan)
if(Vulkan_FOUND)
if(NOT Vulkan_dxc_exe_FOUND)
find_program(Vulkan_dxc_EXECUTABLE
NAMES dxc
HINTS
"$ENV{VULKAN_SDK}/Bin"
"$ENV{VULKAN_SDK}/bin"
)
endif()
if(Vulkan_dxc_EXECUTABLE)
message(STATUS "Found DirectX Shader Compiler under ${Vulkan_dxc_EXECUTABLE}")
else()
message(STATUS "Couldn't find DirectX Shader Compiler executable, make sure it is present in Vulkan SDK or add it manually via Vulkan_dxc_EXECUTABLE cmake variable. HLSL shaders won't be compiled.")
endif()
# slang compiler
if(NOT Vulkan_slang_exe_FOUND)
find_program(Vulkan_slang_EXECUTABLE
NAMES slangc
HINTS
"$ENV{VULKAN_SDK}/Bin"
"$ENV{VULKAN_SDK}/bin"
)
endif()
if(Vulkan_slang_EXECUTABLE)
message(STATUS "Found slang Shader Compiler under ${Vulkan_slang_EXECUTABLE}")
else()
message(STATUS "Couldn't find slang Shader Compiler executable, make sure it is present in Vulkan SDK or add it manually via Vulkan_slang_EXECUTABLE cmake variable. Slang shaders won't be compiled.")
endif()
# glsl compiler
if(NOT Vulkan_glslang_exe_FOUND)
find_program(Vulkan_glslc_EXECUTABLE
NAMES glslc
HINTS
"$ENV{VULKAN_SDK}/Bin"
"$ENV{VULKAN_SDK}/bin"
)
endif()
if(Vulkan_glslc_EXECUTABLE)
message(STATUS "Found glslc Shader Compiler under ${Vulkan_glslc_EXECUTABLE}")
else()
message(STATUS "Couldn't find glslc Shader Compiler executable, make sure it is present in Vulkan SDK or add it manually via Vulkan_glslc_EXECUTABLE cmake variable. GLSL shaders won't be compiled.")
endif()
# glsl compiler
endif()
# globally add VKB_DEBUG for the debug build
add_compile_definitions($<$<CONFIG:DEBUG>:VKB_DEBUG>)
#globally define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS to have designated initializers for the vk-structs
add_compile_definitions(VULKAN_HPP_NO_STRUCT_CONSTRUCTORS)
# globally set -fno-strict-aliasing, needed due to using reinterpret_cast
if (NOT MSVC)
add_compile_options(-fno-strict-aliasing)
endif()
if(MSVC AND (DEFINED CMAKE_C_COMPILER_LAUNCHER))
message(DEBUG "Setting MSVC flags to /Z7 for ccache compatibility. Current flags: ${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
message(DEBUG "New flags: ${CMAKE_CXX_FLAGS_DEBUG}")
endif()
# create output folder
file(MAKE_DIRECTORY output)
# Add path for local cmake scripts
list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_SOURCE_DIR}/bldsys/cmake
${CMAKE_CURRENT_SOURCE_DIR}/bldsys/cmake/module)
include(utils)
include(global_options)
include(sample_helper)
include(check_atomic)
include(component_helper)
# Add third party libraries
add_subdirectory(third_party)
# Framework v2.0 components directory
add_subdirectory(components)
# Add vulkan framework
add_subdirectory(framework)
if(VKB_BUILD_SAMPLES)
# Add vulkan samples
add_subdirectory(samples)
endif()
# Add vulkan app (runs all samples)
add_subdirectory(app)
endif ()
+22
View File
@@ -0,0 +1,22 @@
////
- 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.
-
////
A reminder that this issue tracker is managed by the Khronos Group.
Interactions here should follow the Khronos Code of Conduct (https://www.khronos.org/developers/code-of-conduct), which prohibits aggressive or derogatory language.
Please keep the discussion friendly and civil.
+170
View File
@@ -0,0 +1,170 @@
////
- Copyright (c) 2019-2024, 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.
-
////
= Contributing
:pp: {plus}{plus}
Contributions are encouraged!
This repository welcomes samples of the following types:
* Vulkan API Usage
* Vulkan Extension Usage
* Vulkan Best Practices and/or Performance Guidance
* Unique Vulkan use case or project
If you have a sample that demonstrates Vulkan like any of the above points, then consider contributing to the Vulkan samples repository.
Before you start, check out the requirements and guidelines below.
Following these guidelines can help ensure that your contribution ends up being approved by reviewers and most importantly becomes a valuable addition to the Vulkan Samples repository.
== Quality Checks
Vulkan Samples has a range of quality checks to ensure that we maintain a consistent quality and style across all samples. These include formatting, linting and copyright checks.
To make this process as painless for contributors as possible we use xref:https://pre-commit.com/[pre-commit]. To install pre-commit and the hooks for this repository, run the following commands:
----
pip install pre-commit
pre-commit install
----
If you prefer not to use pre-commit, you can run the checks manually using the following commands:
----
# Run clang-format
./scripts/clang_format.py main
# Run copyright checks
./scripts/copyright.py main --fix
----
Future tooling may be added in the future. If you have any suggestions or feedback, please open an issue on the repository.
== Repository Structure
|===
| folder | description
| `/samples/api/`
| folder containing samples that demonstrate API usage
| `/samples/extensions/`
| folder containing samples that demonstrate API Extensions usage
| `/samples/performance/`
| folder containing samples that demonstrate performance best-practices
| `/shaders/`
| folder containing shaders used by the samples
| `/assets/`
| GIT sub-module with models, scenes and fonts
| `/third_party/`
| folder with commonly used external libraries
|===
== Creating a sample
Follow xref:scripts/README.adoc[this guide] to create a dummy sample and associated build files automatically.
This new sample will be based on the framework of wrapper classes that provide an optimized and convenient system to manage Vulkan objects.
== General Requirements
* Sample folder and description:
** Each sample must be placed in a separate sub-folder within `/samples/api/`, `/samples/performance/` or `/samples/extensions/`.
** Each sample should use a short folder name, using snake_case, that best describes the sample.
** Each sample must be well-documented, include a README.adoc file and ideally include a tutorial file in the root of the sample's folder with a detailed explanation of the sample and a 'best-practice' summary if applicable.
Any images used in the tutorial should be stored in an images/ sub-folder in the sample folder.
* Vendor samples:
** By default each sample is assumed to run on all supported platforms.
Otherwise note any platform restrictions in the sample's documentation.
** If a sample is vendor-specific (i.e.
only runs on certain hardware) please add a `TAG` with the vendor's name in the sample's `CMakeLists.txt`.
* Framework:
** Make use of the available framework whenever possible.
** Do not introduce any new wrapper code.
If what you need is not already a part of the framework, please extend it rather than introduce anything new.
** Alternatively you may use raw Vulkan API calls.
* Code and assets:
** Single source file samples with minimal build complexity are encouraged to make porting to different platforms easier.
** Compiling the sample with the highest warning level and warnings-as-errors (-Wall -Wextra -Werror, or /Wall /WX) is highly recommended.
** Shaders are saved in the `/shaders/` folder, in a separate sub-folder with the same name as the sample sub-folder in `/samples/api/`, `/samples/performance/` or `/samples/extensions/`.
** Assets should be saved in https://github.com/KhronosGroup/Vulkan-Samples-Assets[vulkan-samples-assets].
* License:
** Samples are licensed under the link:LICENSE[LICENSE] file in the root folder.
** The current Contributor License Agreement (CLA) only allows samples to be licensed under the Apache 2.0 license.
** Every source code file must have a Copyright notice and license at the top of the file as described below.
** Assets must have their own license.
* Third party libraries:
** A sample may not depend on a separate installation of a third party library.
** Any third party library that is used needs to be available under a compatible open source license i.e.
MIT or Apache 2.0.
** Any third party library that is used must be included as a sub-module in the `/third_party/` folder.
== Copyright Notice and License Template
To apply the Apache 2.0 License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information for the copyright year or years.
_Don't include the brackets!_ The text should be enclosed in the appropriate comment syntax for the file format.
We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
When contributing to an existing file you may add a new copyright year line under the existing ones.
....
Copyright [yyyy] [name of copyright owner]
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.
....
== Code Style
A common code style like, for instance, the one described by the https://google.github.io/styleguide/cppguide.html[Google C{pp} Style Guide] is recommended.
A sample must consistently apply a single code style.
A `.clang-format` file is included with this repository, please use `clang-format -style=file` to verify the code style.
It is recommended to use `clang-format-15`, which is compatible with the styles in our `.clang-format` file.
== Procedure for Contributing
. Fork the KhronosGroup/Vulkan-Samples repository.
. Add the contribution to the new fork (see <<creating-a-sample,Creating a sample>>).
. Make sure the above requirements are met.
. Make sure the sample is in compliance with the Vulkan specification.
. Make sure the sample code builds and runs on Windows, Linux, macOS and Android.
If you cannot verify on all these target platforms, please note platform restrictions in the sample's README.
. Verify the sample against a recent version of the Vulkan validation layers, either built from source or from the most recent available Vulkan SDK.
. Submit a pull request via github for the contribution, including electronically signing the Khronos Contributor License Agreement (CLA) for the repository using CLA-Assistant.
== Code Reviews
All submissions, including those by project members, are subject to a code review by the Khronos Membership.
GitHub pull requests are used to facilitate the review process, please submit a pull request with your contribution ready for review.
For more information on the review process visit this https://github.com/KhronosGroup/Vulkan-Samples/wiki/Review-Process[link].
== Maintenance
Once a new sample is merged the author is expected to maintain it whenever possible.
Otherwise they should identify a new maintainer that has agreed to take on the responsibility.
+43
View File
@@ -0,0 +1,43 @@
////
- 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.
-
////
= Contributors to the initial release (sorted alphabetically)
* Adam Sawicki
* Alon Or-bach
* Antonio Caggiano
* Attilio Provenzano
* Gary Sweet
* Ioan-Cristian Szabo
* Jeff Bolz
* Jose-Emilio Munoz-Lopez
* Kris Rose
* Lou Kramer
* Marton Tamas
* Matthew Rusch
* Michael Parkin-White
* Peter Harris
* Ryan O'Shea
* Sascha Willems
* Spencer Fricke
* Steven Winston
* Tobias Hector
* Tom Atkinson
* Wasim Abbas
* William Lohry
* Zandro Fargnoli
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 Wasim Abbas (Arm Limited)
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.
+197
View File
@@ -0,0 +1,197 @@
////
- Copyright (c) 2019-2025, 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.
-
////
= Vulkan Samples
// omit in toc
:pp: {plus}{plus}
ifndef::site-gen-antora[]
:toc:
endif::[]
image::banner.jpg[Vulkan Samples banner]
ifndef::site-gen-antora[]
== Vulkan Documentation Site
Documentation for the samples is best viewed at the new link:https://docs.vulkan.org/samples/latest/README.html[Vulkan Documentation Site]. The documentation uses AsciiDoc which isn't fully supported by github.
endif::[]
== Introduction
The Vulkan Samples is collection of resources to help you develop optimized Vulkan applications.
If you are new to Vulkan the xref:samples/api/README.adoc[API samples] are the right place to start.
Additionally you may find the following links useful:
ifdef::site-gen-antora[]
* xref:guide:ROOT:index.adoc[Vulkan Guide]
* xref:tutorial:ROOT:00_Introduction.adoc[Get Started in Vulkan]
endif::[]
ifndef::site-gen-antora[]
* https://docs.vulkan.org/guide/latest/index.html[Vulkan Guide]
* https://docs.vulkan.org/tutorial/latest/index.html[Get Started in Vulkan]
endif::[]
xref:samples/performance/README.adoc[Performance samples] show the recommended best practice together with real-time profiling information.
They are more advanced but also contain a detailed tutorial with more in-detail explanations.
=== Requirements
The samples are written in C{pp} and require a compiler that supports at least C{pp}20. To run the samples, a device that supports at least Vulkan 1.1 or newer is required. Some samples might require a higher Vulkan version and/or support for certain extensions.
=== Goals
* Create a collection of resources that demonstrate best-practice recommendations in Vulkan
* Create tutorials that explain the implementation of best-practices and include performance analysis guides
== Samples
* xref:./samples/README.adoc[Listing of all samples available in this repository]
== General information
* *Project Basics*
** xref:./docs/misc.adoc#controls[Controls]
** xref:./docs/misc.adoc#debug-window[Debug window]
** xref:./scripts/README.adoc[Create a Sample]
* *Vulkan Essentials*
** xref:./samples/vulkan_basics.adoc[How does Vulkan compare to OpenGL ES?
What should you expect when targeting Vulkan?]
* *Misc*
** xref:./docs/misc.adoc#driver-version[Driver version]
** xref:./docs/memory_limits.adoc[Memory limits]
== Setup
Prerequisites: https://git-scm.com/downloads[git] with https://docs.github.com/en/repositories/working-with-files/managing-large-files/installing-git-large-file-storage[git large file storage (git-lfs)].
Clone the repo with submodules using the following command:
----
git clone --recurse-submodules https://github.com/KhronosGroup/Vulkan-Samples.git
cd Vulkan-Samples
----
Follow build instructions for your platform below.
[NOTE]
====
The full repository is very large, and some ISPs appear to have trouble
providing a robust connection to github while the clone is being made.
If you notice problems such as submodules downloading at reported rates in
the tens of kB/s, or fatal timeout errors occurring, these may be due to
network routing issues to github within your ISP's internal network, rather
than anything wrong in your own networking setup.
It can be very difficult to get ISPs to acknowledge such problems exist, much
less to fix them.
One workaround is to switch the repository to use ssh protocol prior to the
submodule download, which can be done via e.g.
[source,sh]
----
git clone git@github.com:KhronosGroup/Vulkan-Samples.git
cd Vulkan-Samples
perl -i -p -e 's|https://(.*?)/|git@\1:|g' .gitmodules
git submodule sync
git submodule update
----
While this can be a good alternative if you are running into this connection
issue, you must have GitHub ssh key authentication setup to use ssh
protocol - see
link:https://docs.github.com/en/authentication/connecting-to-github-with-ssh[Connecting
to GitHub with SSH] for details.
So it is a not a solution we can implement as the repository default.
Another option which may help is to run github through a VPN service.
====
== Build
=== Supported Platforms
* Windows - xref:./docs/build.adoc#windows[Build Guide]
* Linux - xref:./docs/build.adoc#linux[Build Guide]
* Android - xref:./docs/build.adoc#android[Build Guide]
* macOS - xref:./docs/build.adoc#macos[Build Guide]
* iOS - xref:./docs/build.adoc#ios[Build Guide]
== Usage
The following shows some example command line usage on how to configure and run the Vulkan Samples.
> Make sure that you are running the samples from the root directory of the repository.
> Otherwise the samples will not be able to find the assets.
> ./build/app/bin/<BuildType>/<Arch>/vulkan_samples
----
# For the entire usage use
vulkan_samples --help
# For subcommand usage use
vulkan_samples <sub_command> --help
# Run Swapchain Images sample
vulkan_samples sample swapchain_images
# Run AFBC sample in benchmark mode for 5000 frames
vulkan_samples sample afbc --benchmark --stop-after-frame 5000
# Run compute nbody using headless_surface and take a screenshot of frame 5
# Note: headless_surface uses VK_EXT_headless_surface.
# This will create a surface and a Swapchain, but present will be a no op.
# The extension is supported by Swiftshader(https://github.com/google/swiftshader).
# It allows to quickly test content in environments without a GPU.
vulkan_samples sample compute_nbody --headless_surface -screenshot 5
# Run all the performance samples for 10 seconds in each configuration
vulkan_samples batch --category performance --duration 10
# Run Swapchain Images sample on an Android device
adb shell am start-activity -n com.khronos.vulkan_samples/com.khronos.vulkan_samples.SampleLauncherActivity -e sample swapchain_images
----
== License
See link:LICENSE[LICENSE].
This project has several xref:./third_party/README.adoc[third-party dependencies]
This project uses assets from https://github.com/KhronosGroup/Vulkan-Samples-Assets[vulkan-samples-assets].
Each one has its own license.
=== Trademarks
Vulkan is a registered trademark of the Khronos Group Inc.
== Contributions
Donated to Khronos by Arm, with further contributions by Sascha Willems and Adam Sawicki.
See xref:CONTRIBUTORS.adoc[CONTRIBUTORS] for the full contributor list.
Also see xref:CONTRIBUTING.adoc[CONTRIBUTING] for contribution guidelines.
== Related resources
* https://developer.arm.com/documentation/101897/latest/[Mali GPU Best Practices]: A document with recommendations for efficient API usage
+2
View File
@@ -0,0 +1,2 @@
theme: jekyll-theme-slate
exclude: [third_party]
+52
View File
@@ -0,0 +1,52 @@
# Copyright 2022-2024 The Khronos Group Inc.
# SPDX-License-Identifier: Apache-2.0
# Configure Vulkan Guide Antora tree with transformed markup files.
# Branch selection may come later. For now it is the current branch.
function(gatherAntoraAssets)
set(DIRS_TO_SEARCH
app
assets
components
docs
framework
samples
scripts
shaders
)
set(PAGES_DIR_SEARCH)
set(IMAGES_DIR_SEARCH)
foreach (DIR ${DIRS_TO_SEARCH})
list(APPEND PAGES_DIR_SEARCH ${CMAKE_SOURCE_DIR}/${DIR}/*.adoc)
list(APPEND IMAGES_DIR_SEARCH ${CMAKE_SOURCE_DIR}/${DIR}/*.jpg ${CMAKE_SOURCE_DIR}/${DIR}/*.png ${CMAKE_SOURCE_DIR}/${DIR}/*.gif)
endforeach ()
file(GLOB PAGES ${CMAKE_SOURCE_DIR}/*.adoc)
file(GLOB IMAGES ${CMAKE_SOURCE_DIR}/*.jpg ${CMAKE_SOURCE_DIR}/*.png ${CMAKE_SOURCE_DIR}/*.gif)
file(GLOB_RECURSE PAGES_R ${PAGES_DIR_SEARCH})
file(GLOB_RECURSE IMAGES_R ${IMAGES_DIR_SEARCH})
foreach(page ${PAGES})
file(COPY ${page} DESTINATION ${CMAKE_CURRENT_LIST_DIR}/modules/ROOT/pages)
endforeach ()
foreach(image ${IMAGES})
file(COPY ${image} DESTINATION ${CMAKE_CURRENT_LIST_DIR}/modules/ROOT/images)
endforeach ()
foreach (page ${PAGES_R})
file(RELATIVE_PATH relpage ${CMAKE_SOURCE_DIR} ${page})
get_filename_component(directory ${relpage} DIRECTORY)
file(COPY ${page} DESTINATION ${CMAKE_CURRENT_LIST_DIR}/modules/ROOT/pages/${directory})
endforeach ()
foreach(image ${IMAGES_R})
file(RELATIVE_PATH relpage ${CMAKE_SOURCE_DIR} ${image})
get_filename_component(directory ${relpage} DIRECTORY)
file(COPY ${image} DESTINATION ${CMAKE_CURRENT_LIST_DIR}/modules/ROOT/images/${directory})
endforeach ()
endfunction()
if(VKB_GENERATE_ANTORA_SITE)
gatherAntoraAssets()
endif()
+13
View File
@@ -0,0 +1,13 @@
# Copyright 2022-2023 The Khronos Group Inc.
# SPDX-License-Identifier: Apache-2.0
name: samples
title: Vulkan Samples
version: latest
start_page: README.adoc
asciidoc:
attributes:
source-language: asciidoc@
table-caption: false
nav:
- modules/ROOT/nav.adoc
+129
View File
@@ -0,0 +1,129 @@
////
- Copyright (c) 2023-2025, Holochip Inc
- Copyright (c) 2023-2025, Sascha Willems
-
- 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.
-
////
* xref:samples/README.adoc[Samples overview]
* xref:samples/vulkan_basics.adoc[Vulkan basics]
* xref:shaders/README.adoc[Shaders]
* xref:framework/README.adoc[Sample framework]
** xref:components/README.adoc[Framework components]
* xref:samples/api/README.adoc[Api usage samples]
** xref:samples/api/compute_nbody/README.adoc[Compute N-body]
*** xref:samples/api/hpp_compute_nbody/README.adoc[Compute N-body (Vulkan-Hpp)]
** xref:samples/api/dynamic_uniform_buffers/README.adoc[Dynamic uniform buffers]
*** xref:samples/api/hpp_dynamic_uniform_buffers/README.adoc[Dynamic Uniform Buffers (Vulkan-Hpp)]
** xref:samples/api/hdr/README.adoc[HDR]
*** xref:samples/api/hpp_hdr/README.adoc[HDR (Vulkan-Hpp)]
** xref:samples/api/hello_triangle/README.adoc[Hello Triangle]
*** xref:samples/api/hpp_hello_triangle/README.adoc[Hello Triangle (Vulkan-Hpp)]
** xref:samples/api/hello_triangle_1_3/README.adoc[Hello Triangle 1.3]
*** xref:samples/api/hpp_hello_triangle_1_3/README.adoc[Hello Triangle 1.3(Vulkan-Hpp)]
** xref:samples/api/instancing/README.adoc[Instancing]
*** xref:samples/api/hpp_instancing/README.adoc[Instancing (Vulkan-Hpp)]
** xref:samples/api/separate_image_sampler/README.adoc[Separate image sampler]
*** xref:samples/api/hpp_separate_image_sampler/README.adoc[Separate image sampler (Vulkan-Hpp)]
** xref:samples/api/terrain_tessellation/README.adoc[Terrain tessellation]
*** xref:samples/api/hpp_terrain_tessellation/README.adoc[Terrain tessellation (Vulkan-Hpp)]
** xref:samples/api/texture_loading/README.adoc[Texture loading]
*** xref:samples/api/hpp_texture_loading/README.adoc[Texture loading (Vulkan-Hpp)]
** xref:samples/api/texture_mipmap_generation/README.adoc[Texture mipmap generation]
*** xref:samples/api/hpp_texture_mipmap_generation/README.adoc[Texture mipmap generation (Vulkan-Hpp)]
** xref:samples/api/timestamp_queries/README.adoc[Timestamp queries]
*** xref:samples/api/hpp_timestamp_queries/README.adoc[Timestamp queries (Vulkan-Hpp)]
** xref:samples/api/oit_linked_lists/README.adoc[OIT linked lists]
*** xref:samples/api/hpp_oit_linked_lists/README.adoc[OIT linked lists (Vulkan-Hpp)]
** xref:samples/api/oit_depth_peeling/README.adoc[OIT depth peeling]
*** xref:samples/api/hpp_oit_depth_peeling/README.adoc[OIT depth peeling (Vulkan-Hpp)]
* xref:samples/extensions/README.adoc[Extension usage samples]
** xref:samples/extensions/buffer_device_address/README.adoc[Buffer device address]
** xref:samples/extensions/calibrated_timestamps/README.adoc[Calibrated timestamps]
** xref:samples/extensions/conditional_rendering/README.adoc[Conditional rendering]
** xref:samples/extensions/conservative_rasterization/README.adoc[Conservative rasterization]
** xref:samples/extensions/debug_utils/README.adoc[Debug utils]
** xref:samples/extensions/descriptor_buffer_basic/README.adoc[Descriptor buffer basic]
** xref:samples/extensions/descriptor_indexing/README.adoc[Descriptor indexing]
** xref:samples/extensions/dynamic_line_rasterization/README.adoc[Dynamic line rasterization]
** xref:samples/extensions/dynamic_primitive_clipping/README.adoc[Dynamic primitive clipping]
** xref:samples/extensions/dynamic_rendering/README.adoc[Dynamic rendering]
** xref:samples/extensions/dynamic_rendering_local_read/README.adoc[Dynamic rendering local read]
** xref:samples/extensions/extended_dynamic_state2/README.adoc[Extended dynamic state2]
** xref:samples/extensions/fragment_shader_barycentric/README.adoc[Fragment shader barycentric]
** xref:samples/extensions/fragment_shading_rate/README.adoc[Fragment shading rate]
** xref:samples/extensions/fragment_shading_rate_dynamic/README.adoc[Fragment shading rate dynamic]
** xref:samples/extensions/full_screen_exclusive/README.adoc[Full screen exclusive]
** xref:samples/extensions/graphics_pipeline_library/README.adoc[Graphics pipeline library]
** xref:samples/extensions/gshader_to_mshader/README.adoc[Geometry shader to mesh shader]
** xref:samples/extensions/host_image_copy/README.adoc[Host image copy]
** xref:samples/extensions/logic_op_dynamic_state/README.adoc[Logic op dynamic state]
** xref:samples/extensions/memory_budget/README.adoc[Memory budget]
** xref:samples/extensions/mesh_shader_culling/README.adoc[Mesh shader culling]
** xref:samples/extensions/mesh_shading/README.adoc[Mesh shading]
*** xref:samples/extensions/hpp_mesh_shading/README.adoc[Mesh shading (Vulkan-Hpp)]
** xref:samples/extensions/open_cl_interop/README.adoc[OpenCL interop]
** xref:samples/extensions/open_cl_interop_arm/README.adoc[OpenCL interop (Arm)]
** xref:samples/extensions/open_gl_interop/README.adoc[OpenGL interop]
** xref:samples/extensions/portability/README.adoc[Portability]
** xref:samples/extensions/push_descriptors/README.adoc[Push descriptors]
*** xref:samples/extensions/hpp_push_descriptors/README.adoc[Push descriptors (Vulkan-Hpp)]
** xref:samples/extensions/ray_tracing_basic/README.adoc[Raytracing basic]
** xref:samples/extensions/ray_tracing_extended/README.adoc[Raytracing extended]
** xref:samples/extensions/ray_queries/README.adoc[Ray queries]
** xref:samples/extensions/ray_tracing_reflection/README.adoc[Ray tracing reflection]
** xref:samples/extensions/ray_tracing_position_fetch/README.adoc[Ray tracing position fetch]
** xref:samples/extensions/shader_object/README.adoc[Shader Object]
** xref:samples/extensions/shader_debugprintf/README.adoc[Shader Debug Printf]
** xref:samples/extensions/sparse_image/README.adoc[Sparse Image]
** xref:samples/extensions/synchronization_2/README.adoc[Synchronization 2]
** xref:samples/extensions/timeline_semaphore/README.adoc[Timeline semaphore]
** xref:samples/extensions/vertex_dynamic_state/README.adoc[Vertex dynamic state]
** xref:samples/extensions/dynamic_multisample_rasterization/README.adoc[Dynamic multisample rasterization]
* xref:samples/performance/README.adoc[Performance samples]
** xref:samples/performance/16bit_arithmetic/README.adoc[16bit arithmetic]
** xref:samples/performance/16bit_storage_input_output/README.adoc[16bit storage input output]
** xref:samples/performance/afbc/README.adoc[AFBC]
** xref:samples/performance/async_compute/README.adoc[Async compute]
** xref:samples/performance/command_buffer_usage/README.adoc[Command buffer usage]
** xref:samples/performance/constant_data/README.adoc[Constant data]
** xref:samples/performance/descriptor_management/README.adoc[Descriptor management]
** xref:samples/performance/image_compression_control/README.adoc[Image compression control]
** xref:samples/performance/layout_transitions/README.adoc[Layout transitions]
** xref:samples/performance/msaa/README.adoc[MSAA]
** xref:samples/performance/multithreading_render_passes/README.adoc[Multithreading render passes]
** xref:samples/performance/multi_draw_indirect/README.adoc[Multi draw indirect]
** xref:samples/performance/pipeline_barriers/README.adoc[Pipeline barriers]
** xref:samples/performance/pipeline_cache/README.adoc[Pipeline cache]
*** xref:samples/performance/hpp_pipeline_cache/README.adoc[Pipeline cache (Vulkan-Hpp)]
** xref:samples/performance/render_passes/README.adoc[Render passes]
** xref:samples/performance/specialization_constants/README.adoc[Specialization constants]
** xref:samples/performance/subpasses/README.adoc[Subpasses]
** xref:samples/performance/surface_rotation/README.adoc[Surface rotation]
** xref:samples/performance/swapchain_images/README.adoc[Swapchain images]
*** xref:samples/performance/hpp_swapchain_images/README.adoc[Swapchain images (Vulkan-Hpp)]
** xref:samples/performance/texture_compression_basisu/README.adoc[Texture compression basisu]
** xref:samples/performance/texture_compression_comparison/README.adoc[Texture compression comparison]
*** xref:samples/performance/hpp_texture_compression_comparison/README.adoc[Texture compression comparison (Vulkan-Hpp)]
** xref:samples/performance/wait_idle/README.adoc[Wait idle]
* xref:samples/tooling/README.adoc[Tooling samples]
** xref:samples/tooling/profiles/README.adoc[Profiles]
* xref:samples/general/README.adoc[General samples]
** xref:samples/general/mobile_nerf/README.adoc[Mobile NeRF]
** xref:samples/general/mobile_nerf_rayquery/README.adoc[Mobile NeRF Ray Query]
* xref:docs/README.adoc[General documentation]
** xref:docs/build.adoc[Build guide]
** xref:docs/memory_limits.adoc[Memory limits]
** xref:docs/misc.adoc[Miscellaneous]
+206
View File
@@ -0,0 +1,206 @@
# Copyright (c) 2019-2024, 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)
include(android_package)
# create sample app project
project(vulkan_samples LANGUAGES C CXX)
if(IOS AND CMAKE_VERSION VERSION_LESS 3.20)
message(FATAL_ERROR "Configuring iOS apps requires a minimum CMake version of 3.20")
elseif(APPLE AND NOT IOS AND CMAKE_VERSION VERSION_LESS 3.17)
message(FATAL_ERROR "Configuring Xcode for macOS requires a minimum CMake version of 3.17")
endif()
add_subdirectory(plugins)
add_subdirectory(apps)
set(SRC
main.cpp
)
source_group("\\" FILES ${SRC})
# select target type based on platform
if(ANDROID)
if(CMAKE_VS_NsightTegra_VERSION)
list(APPEND SRC ${CMAKE_CURRENT_SOURCE_DIR}/android/AndroidManifest.xml)
endif()
add_library(${PROJECT_NAME} SHARED ${SRC})
elseif(IOS)
list(REMOVE_AT SRC 0)
list(APPEND SRC
${CMAKE_CURRENT_SOURCE_DIR}/ios/main.mm
${CMAKE_CURRENT_SOURCE_DIR}/ios/AppDelegate.h
${CMAKE_CURRENT_SOURCE_DIR}/ios/AppDelegate.m
${CMAKE_CURRENT_SOURCE_DIR}/ios/ViewController.h
${CMAKE_CURRENT_SOURCE_DIR}/ios/ViewController.mm
)
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SRC})
else()
add_executable(${PROJECT_NAME} WIN32 ${SRC})
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE vkb__core vkb__filesystem apps plugins)
# Create android project
if(ANDROID)
if(CMAKE_VS_NsightTegra_VERSION)
set_property(TARGET ${PROJECT_NAME} PROPERTY ANDROID_GUI ON)
set_property(TARGET ${PROJECT_NAME} PROPERTY ANDROID_ASSETS_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/../assets)
set_property(TARGET ${PROJECT_NAME} PROPERTY ANDROID_JAVA_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../bldsys/android/java)
endif()
# Add packaging project only if not using CMake's toolchain
if(CMAKE_SYSTEM_VERSION GREATER 1)
add_android_package_project(
NAME ${PROJECT_NAME}_package
DEPENDS ${PROJECT_NAME}
ASSET_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../assets
JAVA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android/java
RES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android/res
MANIFEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/android/AndroidManifest.xml)
endif()
# Sync assets and shaders
android_sync_folder(PATH ${CMAKE_CURRENT_SOURCE_DIR}/../assets)
android_sync_folder(PATH ${CMAKE_CURRENT_SOURCE_DIR}/../shaders)
endif()
# Create MSVC project
if(MSVC)
# Set VS startup project, working directory to project root, and command line arguments to default sample
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_COMMAND_ARGUMENTS "sample hello_triangle")
#Configure output paths
foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${CONFIG_TYPE} SUFFIX)
string(TOLOWER ${CONFIG_TYPE} CONFIG_DIR)
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${SUFFIX} ${CMAKE_CURRENT_BINARY_DIR}/bin/${CONFIG_DIR}/${TARGET_ARCH})
set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${SUFFIX} ${CMAKE_CURRENT_BINARY_DIR}/lib/${CONFIG_DIR}/${TARGET_ARCH})
set_target_properties(${PROJECT_NAME} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY_${SUFFIX} ${CMAKE_CURRENT_BINARY_DIR}/lib/${CONFIG_DIR}/${TARGET_ARCH})
endforeach()
endif()
# Enable building from XCode for IOS
if(IOS)
set(CMAKE_MACOSX_BUNDLE YES)
if(NOT DEFINED MACOSX_BUNDLE_GUI_IDENTIFIER)
if(${CMAKE_OSX_SYSROOT} STREQUAL "iphoneos" AND DEFINED CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM)
message(FATAL_ERROR "Building for iOS device with a specified development team requires setting MACOSX_BUNDLE_GUI_IDENTIFIER")
else()
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.khronos.vulkansamples)
endif()
endif()
if(NOT DEFINED CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM)
if(NOT DEFINED CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED)
if(${CMAKE_OSX_SYSROOT} STREQUAL "iphoneos")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "YES")
else()
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO")
endif()
endif()
if(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED)
message(FATAL_ERROR "Building for iOS with code signing requires setting CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM; note it is safe to build for iOS Simulator without code signing")
else()
message(STATUS "Building for iOS device or iOS Simulator without a code signing identity; turning off code signing")
set_target_properties(${PROJECT_NAME} PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY "NO"
)
endif ()
else()
message(STATUS "Building for iOS device or iOS Simulator with a code signing identity; turning on code signing")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "YES")
set_target_properties(${PROJECT_NAME} PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "YES"
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY "YES"
)
endif ()
# No need to search for Vulkan package or MoltenVK library, Vulkan cache variables already defined on Apple platforms by global_options.cmake
if(Vulkan_LIBRARY AND ${Vulkan_VERSION} VERSION_GREATER_EQUAL 1.3.278)
target_sources(${PROJECT_NAME} PRIVATE
${Vulkan_Target_SDK}/iOS/share/vulkan
)
set_source_files_properties(
${Vulkan_Target_SDK}/iOS/share/vulkan
PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)
endif ()
target_sources(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../assets
${CMAKE_CURRENT_SOURCE_DIR}/../shaders
${CMAKE_CURRENT_SOURCE_DIR}/ios/launch.storyboard
${CMAKE_CURRENT_SOURCE_DIR}/ios/Storyboard.storyboard
)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/ios/launch.storyboard
${CMAKE_CURRENT_SOURCE_DIR}/ios/Storyboard.storyboard
${CMAKE_CURRENT_SOURCE_DIR}/../assets
${CMAKE_CURRENT_SOURCE_DIR}/../shaders
PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)
set(FRAMEWORKS_TO_EMBED)
if(Vulkan_MoltenVK_LIBRARY)
list(APPEND FRAMEWORKS_TO_EMBED "${Vulkan_MoltenVK_LIBRARY};")
else()
message(FATAL_ERROR "Can't find MoltenVK library. Please install the Vulkan SDK or MoltenVK project and set VULKAN_SDK.")
endif()
if(Vulkan_LIBRARY)
list(APPEND FRAMEWORKS_TO_EMBED "${Vulkan_LIBRARY};")
endif()
if(Vulkan_Layer_VALIDATION)
# trouble is can't turn this on/off if XCode decides to build debug and we're configured for release. Need to revist
# note the Vulkan validation layer must be present and enabled even in release mode for the shader_debugprintf sample
#if(("${VKB_DEBUG}" STREQUAL "ON") OR ("${VKB_VALIDATION_LAYERS}" STREQUAL "ON"))
list(APPEND FRAMEWORKS_TO_EMBED "${Vulkan_Layer_VALIDATION}")
#endif()
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/ios/Info.plist
# These are already defined by the ios Info.plist file specified above
#MACOSX_BUNDLE_SHORT_VERSION_STRING 1.0.0
#MACOSX_BUNDLE_BUNDLE_VERSION 1.0.0
#MACOSX_BUNDLE_BUNDLE_NAME "vulkan samples"
)
set_target_properties(${PROJECT_NAME} PROPERTIES
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER ${MACOSX_BUNDLE_GUI_IDENTIFIER}
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES"
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks"
XCODE_ATTRIBUTE_CODE_SIGN_STYLE "Automatic" # already default value
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer"
XCODE_EMBED_FRAMEWORKS "${FRAMEWORKS_TO_EMBED}"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY "YES"
XCODE_ATTRIBUTE_SKIP_INSTALL NO
XCODE_ATTRIBUTE_INSTALL_PATH "$(LOCAL_APPS_DIR)"
XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING NO
XCODE_SCHEME_ARGUMENTS "sample hello_triangle"
)
elseif(APPLE)
# Set Xcode working directory to project root, and command line arguments to default sample
set_target_properties(${PROJECT_NAME} PROPERTIES
XCODE_SCHEME_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
XCODE_SCHEME_ARGUMENTS "sample hello_triangle"
)
endif()
+59
View File
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019-2024, 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.
-
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="1"
android:versionName="1.0">
<application android:label="@string/app_name"
android:debuggable="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning,HardcodedDebugMode">
<activity android:name="com.khronos.vulkan_samples.SampleLauncherActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.khronos.vulkan_samples.NativeSampleActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="fullSensor">
<meta-data android:name="android.app.lib_name"
android:value="@string/native_lib_name" />
</activity>
<provider
android:authorities="${applicationId}.provider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>
Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

@@ -0,0 +1,152 @@
/* Copyright (c) 2019-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.
*/
package com.khronos.vulkan_samples;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import com.khronos.vulkan_samples.common.Utils;
import java.util.ArrayList;
import java.util.List;
public class FilterDialog extends DialogFragment {
// The adapter that is notified by a filter changing
private ViewPagerAdapter adapter;
// Saved raw filters that are used to update the adapter
private List<String> filters;
// Capitalised raw filters
private List<String> labels;
// Save state of the current applied filter
// This is used to initialise the filter every time it is opened
protected List<Boolean> values;
// Mutable copy of the saved state
// This is used when a dialog is open to track the state of the labels
// If a filter is applied values is replaced with this list; otherwise This is discarded
protected List<Boolean> alteredValues;
public void setup(ViewPagerAdapter adapter, List<String> filters) {
this.adapter = adapter;
this.filters = new ArrayList<>(filters);
this.labels = new ArrayList<>(filters.size());
this.values = new ArrayList<>(filters.size());
// Initialise labels only once
// Default set all filters to checked
for (int i = 0; i < filters.size(); ++i) {
this.labels.add(i, Utils.capitalize(filters.get(i)));
this.values.add(i, true);
}
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Initial labels and values for the list of filters
final CharSequence[] labels = this.labels.toArray(new CharSequence[0]);
boolean[] values = Utils.toBoolArray(this.values);
// Initiate the mutable filter list
this.alteredValues = new ArrayList<>(this.values);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
.setTitle("Filter Samples by Tag")
.setMultiChoiceItems(labels, values, new FilterMultiChoiceClickListener(this))
.setPositiveButton("Apply", new FilterClickListener(this));
return builder.create();
}
/**
* Notify the adapter that the current applied filter has changed
*/
protected void notifyAdapter() {
adapter.applyFilter(getFilter());
adapter.notifyDataSetChanged();
}
/**
* Get all raw filters that have been applied
*
* @return List of applied filters
*/
public List<String> getFilter() {
List<String> filters = new ArrayList<>();
for (int i = 0; i < this.filters.size(); i++) {
if (this.values.get(i)) {
filters.add(this.filters.get(i));
}
}
return filters;
}
}
/**
* Changes to a filter item's state must not persist if the dialog is closed without applying a filter.
* Update alteredValues, changes are discarded if the filter is not applied
*/
class FilterMultiChoiceClickListener implements DialogInterface.OnMultiChoiceClickListener {
private final FilterDialog dialog;
FilterMultiChoiceClickListener(FilterDialog dialog) {
this.dialog = dialog;
}
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (which > this.dialog.alteredValues.size() || which < 0) {
// Which is not in the label array - should never happen
return;
}
this.dialog.alteredValues.set(which, isChecked);
}
}
/**
* When applying a filter override the current values and then notify the adapter that the current filter has been changed
*/
class FilterClickListener implements DialogInterface.OnClickListener {
private final FilterDialog dialog;
FilterClickListener(FilterDialog dialog) {
this.dialog = dialog;
}
@Override
public void onClick(DialogInterface dialog, int id) {
this.dialog.values = new ArrayList<>(this.dialog.alteredValues);
this.dialog.notifyAdapter();
}
}
@@ -0,0 +1,102 @@
/* Copyright (c) 2019-2024, 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.
*/
package com.khronos.vulkan_samples;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.FileProvider;
import android.view.View;
import com.google.androidgamesdk.GameActivity;
import com.khronos.vulkan_samples.common.Notifications;
import java.io.File;
import java.util.concurrent.Semaphore;
public class NativeSampleActivity extends GameActivity {
private Context context;
private final Semaphore semaphore = new Semaphore(0, true);
@Override
protected void onCreate(Bundle instance) {
super.onCreate(instance);
Notifications.initNotificationChannel(this);
context = this;
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
/***
* Handle the application when an error is thrown and display a message
*/
public void fatalError(String message) {
final NativeSampleActivity activity = this;
ApplicationInfo applicationInfo = activity.getApplicationInfo();
this.runOnUiThread(new Runnable() {
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Vulkan Samples");
builder.setMessage(message);
builder.setPositiveButton("Close", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
semaphore.release();
}
});
builder.setCancelable(false);
AlertDialog dialog = builder.create();
dialog.show();
}
});
try {
semaphore.acquire();
}
catch (InterruptedException e) { }
activity.finish();
}
}
@@ -0,0 +1,70 @@
/* Copyright (c) 2019-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.
*/
package com.khronos.vulkan_samples;
import android.annotation.SuppressLint;
import android.content.Context;
import androidx.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.khronos.vulkan_samples.model.Sample;
import java.util.List;
public class SampleArrayAdapter extends ArrayAdapter<Sample> {
SampleArrayAdapter(Context context, List<Sample> sample_list) {
super(context, R.layout.listview_item, sample_list);
}
/**
* Get a view for a position in the sample list
*
* @param position The position in the list
* @param view The view object that was previously at this position
* @param parent The parent view group
* @return A view object representing a given sample at a list position
*/
@NonNull
@SuppressLint("SetTextI18n")
@Override
public View getView(int position, View view, @NonNull ViewGroup parent) {
// Recycle view objects
if (view == null) {
view = LayoutInflater.from(getContext()).inflate(R.layout.listview_item, parent, false);
}
Sample sample = getItem(position);
assert sample != null;
TextView title = view.findViewById(R.id.title_text);
title.setText(sample.getName());
TextView description = view.findViewById(R.id.description_text);
description.setText(sample.getDescription());
TextView vendorTag = view.findViewById(R.id.vendor_text);
vendorTag.setText(sample.getTagText());
return view;
}
}
@@ -0,0 +1,336 @@
/* Copyright (c) 2019-2024, 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.
*/
package com.khronos.vulkan_samples;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import androidx.appcompat.widget.Toolbar;
import com.khronos.vulkan_samples.common.Notifications;
import com.khronos.vulkan_samples.model.Permission;
import com.khronos.vulkan_samples.model.Sample;
import com.khronos.vulkan_samples.model.SampleStore;
import com.khronos.vulkan_samples.views.PermissionView;
import com.khronos.vulkan_samples.views.SampleListView;
public class SampleLauncherActivity extends AppCompatActivity {
SampleListView sampleListView;
PermissionView permissionView;
private boolean isBenchmarkMode = false;
private boolean isHeadless = false;
public SampleStore samples;
// Required sample permissions
List<Permission> permissions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (loadNativeLibrary(getResources().getString(R.string.native_lib_name))) {
// Get sample info from cpp cmake generated file
samples = new SampleStore(Arrays.asList(getSamples()));
}
// Required Permissions
permissions = new ArrayList<>();
if (checkPermissions()) {
// Permissions previously granted skip requesting them
parseArguments();
showSamples();
} else {
// Chain request permissions
requestNextPermission();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem checkable = menu.findItem(R.id.menu_benchmark_mode);
checkable.setChecked(isBenchmarkMode);
checkable = menu.findItem(R.id.menu_headless);
checkable.setChecked(isHeadless);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.filter_button) {
sampleListView.dialog.show(getSupportFragmentManager(), "filter");
return true;
} else if(item.getItemId() == R.id.menu_run_samples) {
String category = "";
ViewPagerAdapter adapter = ((ViewPagerAdapter) sampleListView.viewPager.getAdapter());
if (adapter != null) {
category = adapter.getCurrentFragment().getCategory();
}
List<String> arguments = new ArrayList<>();
arguments.add("batch");
arguments.add("--category");
arguments.add(category);
arguments.add("--tag");
arguments.addAll(sampleListView.dialog.getFilter());
String[] sa = {};
launchWithCommandArguments(arguments.toArray(sa));
return true;
} else if(item.getItemId() == R.id.menu_benchmark_mode) {
isBenchmarkMode = !item.isChecked();
item.setChecked(isBenchmarkMode);
return true;
} else if(item.getItemId() == R.id.menu_headless) {
isHeadless = !item.isChecked();
item.setChecked(isHeadless);
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
requestNextPermission();
}
/**
* Load a native library
*
* @param native_lib_name Native library to load
* @return True if loaded correctly; False otherwise
*/
private boolean loadNativeLibrary(String native_lib_name) {
boolean status = true;
try {
System.loadLibrary(native_lib_name);
} catch (UnsatisfiedLinkError e) {
Toast.makeText(getApplicationContext(), "Native code library failed to load.", Toast.LENGTH_SHORT).show();
status = false;
}
return status;
}
/**
* Chain request permissions from the required permission list. When called the
* next unrequested permission with be requested If all permission are requested
* but not all granted; requested states will be reset and the PermissionView
* will be shown
*/
public void requestNextPermission() {
boolean granted = true;
for (Permission permission : permissions) {
// Permission previously requested but not granted
if (!permission.granted(getApplication())) {
// Permission not previously requested - request it
if (!permission.isRequested()) {
permission.request(this);
return;
}
granted = false;
}
}
if (granted) {
parseArguments();
showSamples();
} else {
// Reset all permissions request state so they can be requested again
for (Permission permission : permissions) {
permission.setRequested(false);
}
showPermissionsMessage();
}
}
/**
* Check all required permissions have been granted
*
* @return True if all granted; False otherwise
*/
public boolean checkPermissions() {
for (Permission permission : permissions) {
if (!permission.granted(getApplicationContext())) {
return false;
}
}
return true;
}
/**
* Show/Create the Permission View. Hides all other views
*/
public void showPermissionsMessage() {
if (permissionView == null) {
permissionView = new PermissionView(this);
}
if (sampleListView != null) {
sampleListView.hide();
}
permissionView.show();
}
/**
* Show/Create the Sample View. Hides all other views
*/
public void showSamples() {
if (sampleListView == null) {
sampleListView = new SampleListView(this);
}
if (permissionView != null) {
permissionView.hide();
}
sampleListView.show();
}
// Allow Orientation locking for testing
@SuppressLint("SourceLockedOrientationActivity")
public void parseArguments() {
// Handle argument passing
Bundle extras = this.getIntent().getExtras();
if (extras != null) {
if (extras.containsKey("cmd")) {
String[] commands = null;
String[] command_arguments = extras.getStringArray("cmd");
String command = extras.getString("cmd");
if (command_arguments != null) {
commands = command_arguments;
} else if (command != null) {
commands = command.split("[ ]+");
}
if (commands != null) {
for (String cmd : commands) {
if (cmd.equals("test")) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
}
}
launchWithCommandArguments(commands);
finishAffinity();
}
} else if (extras.containsKey("sample")) {
launchSample(extras.getString("sample"));
finishAffinity();
} else if (extras.containsKey("test")) {
launchTest(extras.getString("test"));
finishAffinity();
}
}
}
/**
* Set arguments of the Native Activity You may also use a String[]
*
* @param args A string array of arguments
*/
public void setArguments(String... args) {
List<String> arguments = new ArrayList<>(Arrays.asList(args));
if (isBenchmarkMode) {
arguments.add("--benchmark");
}
if (isHeadless) {
arguments.add("--headless_surface");
}
String[] argArray = new String[arguments.size()];
sendArgumentsToPlatform(arguments.toArray(argArray));
}
public void launchWithCommandArguments(String... args) {
setArguments(args);
Intent intent = new Intent(SampleLauncherActivity.this, NativeSampleActivity.class);
startActivity(intent);
}
public void launchTest(String testID) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
launchWithCommandArguments("test", testID);
}
public void launchSample(String sampleID) {
Sample sample = samples.findByID(sampleID);
if (sample == null) {
Notifications.toast(this, "Could not find sample " + sampleID);
showSamples();
return;
}
launchWithCommandArguments("sample", sampleID);
}
/**
* Get samples from the Native Application
*
* @return A list of Samples that are currently installed in the Native
* Application
*/
private native Sample[] getSamples();
/**
* Set the arguments of the Native Application
*
* @param args The arguments that are to be passed to the app
*/
private native void sendArgumentsToPlatform(String[] args);
}
@@ -0,0 +1,104 @@
/* Copyright (c) 2019-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.
*/
package com.khronos.vulkan_samples;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import com.khronos.vulkan_samples.model.Sample;
import java.util.ArrayList;
import java.util.List;
public class TabFragment extends Fragment {
private String category;
private List<Sample> sampleList = new ArrayList<>();
private AdapterView.OnItemClickListener clickListener;
/**
* Create a new Tab Fragment Instance
*
* @param category The Title of the TabFragment
* @param sampleList The Samples that this tab will render
* @param clickListener The listener used when a item is clicked
* @return A new Tab Fragment
*/
public static Fragment getInstance(String category, List<Sample> sampleList, AdapterView.OnItemClickListener clickListener) {
Bundle bundle = new Bundle();
bundle.putString("category", category);
TabFragment tabFragment = new TabFragment();
tabFragment.setArguments(bundle);
tabFragment.setSampleList(sampleList);
tabFragment.setClickListener(clickListener);
return tabFragment;
}
/**
* Set the sample list that the fragment should render
*
* @param list A list of samples
*/
public void setSampleList(List<Sample> list) {
this.sampleList = list;
}
/**
* Set the action to perform when a sample list item is clicked
*
* @param clickListener A OnItemClickListener
*/
public void setClickListener(AdapterView.OnItemClickListener clickListener) {
this.clickListener = clickListener;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
assert getArguments() != null;
category = getArguments().getString("category");
setRetainInstance(true);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tab, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ListView listView = view.findViewById(R.id.sample_list);
SampleArrayAdapter sampleArrayAdapter = new SampleArrayAdapter(view.getContext(), sampleList);
listView.setAdapter(sampleArrayAdapter);
listView.setOnItemClickListener(this.clickListener);
}
public String getCategory() {
return category;
}
}
@@ -0,0 +1,105 @@
/* Copyright (c) 2019-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.
*/
package com.khronos.vulkan_samples;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import android.view.ViewGroup;
import android.widget.AdapterView;
import com.khronos.vulkan_samples.model.Sample;
import com.khronos.vulkan_samples.model.SampleStore;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private TabFragment currentFragment;
private List<Sample> viewableSamples = new ArrayList<>();
private final SampleStore samples;
private final AdapterView.OnItemClickListener clickListener;
public ViewPagerAdapter(FragmentManager manager, SampleStore samples, AdapterView.OnItemClickListener clickListener) {
super(manager);
this.samples = samples;
this.clickListener = clickListener;
applyFilter(samples.getTags());
}
public void setDialog(FilterDialog dialog) {
dialog.setup(this, samples.getTags());
}
/**
* Modifies the filter so that the viewableSamples updates
*/
public void applyFilter(List<String> filterTags) {
viewableSamples = new ArrayList<>(samples.getByTags(filterTags));
}
@NonNull
@Override
public Fragment getItem(int position) {
List<Sample> fragmentSamples = new ArrayList<>();
String category = samples.getCategories().get(position);
assert category != null;
for (Sample sample : Objects.requireNonNull(samples.getByCategory(category))) {
for (Sample viewableSample : this.viewableSamples) {
if (sample.equals(viewableSample)) {
fragmentSamples.add(sample);
}
}
}
return TabFragment.getInstance(category, fragmentSamples, clickListener);
}
public int getItemPosition(@NonNull Object object) {
return POSITION_NONE;
}
@Override
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
if (getCurrentFragment() != object) {
currentFragment = (TabFragment) object;
}
super.setPrimaryItem(container, position, object);
}
@Override
public int getCount() {
return samples.getCategoryIndex().size();
}
@Override
public CharSequence getPageTitle(int position) {
return samples.getCategories().get(position);
}
TabFragment getCurrentFragment() {
return currentFragment;
}
}
@@ -0,0 +1,95 @@
/* Copyright (c) 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.
*/
package com.khronos.vulkan_samples.common;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import android.widget.Toast;
import android.content.Context;
import com.khronos.vulkan_samples.R;
public class Notifications {
private static final String NOTIFICATION_PREFS = "NOTIFICATION_PREFS";
private static final String NOTIFICATION_KEY = "NOTIFICATION_KEY";
public static final String CHANNEL_ID = "vkb";
private static int initialId = 0;
public static void initNotificationChannel(Context context) {
// Create Notification Channel API 26+
//
// API 26+ implements notifications using a channel where notifications are submitted to channel
// The following initialises the channel used by vkb to push notifications to.
// IMPORTANCE_HIGH = push notifications
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_name), NotificationManager.IMPORTANCE_HIGH);
channel.setDescription(context.getString(R.string.channel_desc));
NotificationManager nm = context.getSystemService(NotificationManager.class);
nm.createNotificationChannel(channel);
}
}
public static int getNotificationId(Context context) {
SharedPreferences prefs = context.getSharedPreferences(NOTIFICATION_PREFS, Context.MODE_PRIVATE);
int id = initialId;
if (prefs.contains(NOTIFICATION_KEY)) {
id = prefs.getInt(NOTIFICATION_KEY, initialId);
}
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(NOTIFICATION_KEY, id + 1);
editor.apply();
return id;
}
/**
* Create a push notification from JNI with a message
*
* @param message A string of a message to be shown
*/
public static void notification(Context context, final String message) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.icon)
.setContentTitle("Vulkan Samples Error")
.setContentText(message)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(message))
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat nm = NotificationManagerCompat.from(context);
nm.notify(getNotificationId(context), builder.build());
}
/**
* Create a toast from JNI on the android main UI thread with a message
*
* @param message A string of a message to be shown
*/
public static void toast(final Context context, final String message) {
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, message, Toast.LENGTH_LONG).show());
}
}
@@ -0,0 +1,96 @@
/* Copyright (c) 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.
*/
package com.khronos.vulkan_samples.common;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Utils {
/**
* A helper to capitalize a string
*
* @param str The string to be capitalized
* @return A capitalized string
*/
public static String capitalize(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
/**
* Convert List of Boolean to primitive boolean array
* @param list The list to be converted
* @return A primitive boolean array containing the lists values
*/
public static boolean[] toBoolArray(List<Boolean> list) {
boolean[] booleans = new boolean[list.size()];
for (int i = 0; i < list.size(); i++) {
booleans[i] = list.get(i);
}
return booleans;
}
/**
* Convert List of String to String array
* @param list The list to be converted
* @return A String array containing the lists values
*/
public static String[] toStringArray(List<String> list) {
String[] strings = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
strings[i] = list.get(i);
}
return strings;
}
/**
* Comparator orders with a predefined list
*/
public static class PredefinedOrderComparator implements Comparator<String> {
private final List<String> defined_order;
public PredefinedOrderComparator(String... predefined_order) {
defined_order = Collections.unmodifiableList(Arrays.asList(predefined_order));
}
@Override
public int compare(String o1, String o2) {
// Remove duplicates
if (o1.equals(o2)) {
return 0;
}
int ret;
int o1_order = defined_order.indexOf(o1);
int o2_order = defined_order.indexOf(o2);
//if neither are found in the order list, then do natural sort - string comparison
if (o1_order < 0 && o2_order < 0) ret = o1.compareTo(o2);
//if only one is found in the order list, float it above the other
else if (o1_order < 0) ret = 1;
else if (o2_order < 0) ret = -1;
//if both are found in the order list, then do the index comparision
else ret = o1_order - o2_order;
return ret;
}
}
}
@@ -0,0 +1,91 @@
/* Copyright (c) 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.
*/
package com.khronos.vulkan_samples.model;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class Permission {
private final String name;
private final int code;
private boolean requested = false;
public Permission(String name, int code) {
this.name = name;
this.code = code;
}
/**
* Set the requested state of the permission
*
* @param requested The desired requested state
*/
public void setRequested(boolean requested) {
this.requested = requested;
}
/**
* Query if the permission has already been requested
*
* @return True if previously requested; false otherwise
*/
public boolean isRequested() {
return requested;
}
/**
* Get the name of the permission
*
* @return The permissions name
*/
public String getName() {
return name;
}
/**
* Get the code of the permission
*
* @return The permissions code
*/
public int getCode() {
return code;
}
/**
* Query whether the permission has been granted for the App
*
* @param ctx The activity context that needs to be queried for the permission
* @return True if permission granted; false otherwise
*/
public boolean granted(Context ctx) {
return ContextCompat.checkSelfPermission(ctx, name) == PackageManager.PERMISSION_GRANTED;
}
/**
* Request the permission for a given Activity
*
* @param activity Activity to request the permission for
*/
public void request(Activity activity) {
ActivityCompat.requestPermissions(activity, new String[]{name}, code);
requested = true;
}
}
@@ -0,0 +1,164 @@
/* Copyright (c) 2019-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.
*/
package com.khronos.vulkan_samples.model;
import android.text.TextUtils;
import com.khronos.vulkan_samples.common.Utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class Sample implements Comparable<Sample> {
private final String id;
private final String category;
private final String author;
private final String name;
private final String description;
private String tagText;
private final List<String> tags;
public Sample(String id, String category, String author, String name, String description, String[] tags) {
this.id = id;
this.category = category;
this.author = author;
this.name = name;
this.description = description;
this.tags = new LinkedList<>(Arrays.asList(tags));
}
/**
* Generate the Tag Text that is shown in the sample list
*
* @return A concatenated string of a samples tags
*/
private String generateTagText() {
List<String> formatted_tags = new ArrayList<>(this.tags.size());
for (String tag : this.tags) {
formatted_tags.add(Utils.capitalize(tag));
}
// If the sample has a tag other than "Any" then "Any" can be removed
if (formatted_tags.size() > 1) {
formatted_tags.remove("Any");
}
return TextUtils.join(", ", formatted_tags);
}
/**
* Get the Sample's ID
*
* @return A Sample ID
*/
public String getId() {
return id;
}
/**
* Get the sample's category
*
* @return The sample's category
*/
public String getCategory() {
return category;
}
/**
* Get the sample's author
*
* @return The sample's author
*/
public String getAuthor() {
return author;
}
/**
* Get the sample's name
*
* @return The sample's name
*/
public String getName() {
return name;
}
/**
* Get the sample's description
*
* @return The sample's description
*/
public String getDescription() {
return description;
}
/**
* Get the sample's tags
*
* @return The sample's tags
*/
public List<String> getTags() {
return tags;
}
/**
* Get the sample's tag text
*
* @return The sample's tag text
*/
public String getTagText() {
if (tagText == null) {
tagText = generateTagText();
}
return tagText;
}
/**
* Checks whether two samples are equal
* Can be used with a HashMap
*
* @return True if samples are equal; false otherwise
*/
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Sample) {
Sample sample = (Sample) object;
return this.id.equals(sample.id);
}
return false;
}
/**
* Used when comparing two samples - Alphabetical Case Insensitive
* Sample id's are unique so this is used to compare
*
* @param sample To compare too
* @return - if less, 0 if equal + if greater than
*/
public int compareTo(Sample sample) {
return sample.id.compareToIgnoreCase(this.id);
}
}
@@ -0,0 +1,159 @@
/* Copyright (c) 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.
*/
package com.khronos.vulkan_samples.model;
import com.khronos.vulkan_samples.common.Utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* A one stop store of samples that are pre indexed for use in the App
*/
public class SampleStore {
private final Set<Sample> samples = new TreeSet<>();
private final Set<String> categories = new TreeSet<>(new Utils.PredefinedOrderComparator("api", "performance", "extensions"));
private final Map<String, List<Sample>> categoryIndex = new HashMap<>();
private final Set<String> tags = new TreeSet<>(new Utils.PredefinedOrderComparator("any"));
private final Map<String, List<Sample>> tagIndex = new HashMap<>();
public SampleStore(List<Sample> samples) {
if (samples == null) {
samples = new ArrayList<>();
}
// Index all samples by tag and by category
for (Sample sample : samples) {
if (sample == null) {
continue;
}
this.samples.add(sample);
if (!categoryIndex.containsKey(sample.getCategory())) {
categoryIndex.put(sample.getCategory(), new ArrayList<>());
}
List<Sample> category = categoryIndex.get(sample.getCategory());
if (category != null) {
category.add(sample);
}
for (String tag : sample.getTags()) {
if (!tagIndex.containsKey(tag)) {
tagIndex.put(tag, new ArrayList<>());
}
List<Sample> index = tagIndex.get(tag);
if (index != null) {
index.add(sample);
}
this.tags.add(tag);
}
this.categories.add(sample.getCategory());
}
}
/**
* Find a sample by its id
*
* @param id of a given sample
* @return A sample if it is found
*/
public Sample findByID(String id) {
for (Sample sample : samples) {
if (sample.getId().equals(id)) {
return sample;
}
}
return null;
}
/**
* Get the category index
*
* @return A map of category to samples
*/
public Map<String, List<Sample>> getCategoryIndex() {
return this.categoryIndex;
}
/**
* Get all category names
*
* @return A list of category names
*/
public List<String> getCategories() {
return new ArrayList<>(this.categories);
}
/**
* Get all tag names
*
* @return A list of tag names
*/
public List<String> getTags() {
return new ArrayList<>(this.tags);
}
/**
* Get a list of sample by tag name
*
* @return A list of samples
*/
public List<Sample> getByTag(String tag) {
return this.tagIndex.get(tag);
}
/**
* Get a list of sample by multiple tag names
*
* @return A list of samples
*/
public List<Sample> getByTags(List<String> tags) {
Set<Sample> samples = new HashSet<>();
for (String tag : tags) {
Collection<Sample> samplesByTag = getByTag(tag);
if (samplesByTag != null) {
samples.addAll(samplesByTag);
}
}
return new ArrayList<>(samples);
}
/**
* Get a list of sample by category name
*
* @return A list of samples
*/
public List<Sample> getByCategory(String category) {
return this.categoryIndex.get(category);
}
}
@@ -0,0 +1,70 @@
/* Copyright (c) 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.
*/
package com.khronos.vulkan_samples.views;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.khronos.vulkan_samples.R;
import com.khronos.vulkan_samples.SampleLauncherActivity;
/**
* A container for all elements related to the permission view
*/
public class PermissionView {
private final Button buttonPermissions;
private final TextView textPermissions;
public PermissionView(SampleLauncherActivity activity) {
buttonPermissions = activity.findViewById(R.id.button_permissions);
buttonPermissions.setOnClickListener(new CheckPermissionClickListener(activity));
textPermissions = activity.findViewById(R.id.text_permissions);
}
/**
* Show the permission view
*/
public void show() {
buttonPermissions.setVisibility(View.VISIBLE);
textPermissions.setVisibility(View.VISIBLE);
}
/**
* Hide the permission view
*/
public void hide() {
buttonPermissions.setVisibility(View.INVISIBLE);
textPermissions.setVisibility(View.INVISIBLE);
}
}
/**
* Click listener for the Permission View button
*/
class CheckPermissionClickListener implements View.OnClickListener {
private final SampleLauncherActivity activity;
CheckPermissionClickListener(SampleLauncherActivity activity) {
this.activity = activity;
}
public void onClick(View v) {
activity.requestNextPermission();
}
}
@@ -0,0 +1,83 @@
/* 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.
*/
package com.khronos.vulkan_samples.views;
import com.google.android.material.tabs.TabLayout;
import androidx.viewpager.widget.ViewPager;
import android.view.View;
import android.widget.AdapterView;
import com.khronos.vulkan_samples.FilterDialog;
import com.khronos.vulkan_samples.R;
import com.khronos.vulkan_samples.SampleLauncherActivity;
import com.khronos.vulkan_samples.ViewPagerAdapter;
import com.khronos.vulkan_samples.model.Sample;
/**
* A container for all elements related to the sample view
*/
public class SampleListView {
private final TabLayout tabLayout;
public ViewPager viewPager;
public FilterDialog dialog;
public SampleListView(SampleLauncherActivity activity) {
viewPager = activity.findViewById(R.id.viewpager);
ViewPagerAdapter adapter = new ViewPagerAdapter(activity.getSupportFragmentManager(), activity.samples, new SampleItemClickListener(activity));
viewPager.setAdapter(adapter);
dialog = new FilterDialog();
adapter.setDialog(dialog);
tabLayout = activity.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
/**
* Show the sample view
*/
public void show() {
tabLayout.setVisibility(View.VISIBLE);
viewPager.setVisibility(View.VISIBLE);
}
/**
* Hide the sample view
*/
public void hide() {
tabLayout.setVisibility(View.INVISIBLE);
viewPager.setVisibility(View.INVISIBLE);
}
}
/**
* Click listener for a Sample List Item
* Start the Native Activity for the clicked Sample
*/
class SampleItemClickListener implements AdapterView.OnItemClickListener {
private final SampleLauncherActivity activity;
SampleItemClickListener(SampleLauncherActivity activity) {
this.activity = activity;
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String sampleID = ((Sample) parent.getItemAtPosition(position)).getId();
activity.launchSample(sampleID);
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+74
View File
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019-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.
-
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:titleTextAppearance="@style/Toolbar.TitleText"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="104dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<TextView
android:id="@+id/text_permissions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:padding="50dp"
android:visibility="invisible"
android:text="@string/permissions_text" />
<Button
android:id="@+id/button_permissions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_alignBottom="@+id/text_permissions"
android:visibility="invisible"
android:text="@string/permissions_button" />
</RelativeLayout>
+39
View File
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019-2020, 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.
-
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:padding="10dp"
android:textSize="40sp"
android:textStyle="bold"/>
<ListView
android:id="@+id/sample_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
</RelativeLayout>
+64
View File
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019-2020, 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.
-
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/title_text"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="10dip"
android:paddingTop="10dip"
android:textSize="16dip"
android:textStyle="bold"
tools:text="A Sample Title">
</TextView>
<TextView
android:id="@+id/description_text"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/title_text"
android:paddingLeft="10dip"
android:paddingBottom="10dip"
android:textSize="14dip"
android:textStyle="italic"
tools:text="A Sample Description">
</TextView>
<TextView
android:id="@+id/vendor_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:gravity="right"
android:paddingTop="4dip"
android:paddingRight="10dip"
android:textColor="@color/colorPrimary"
android:textSize="12dip"
android:textStyle="italic"
tools:text="Tag, Tag">
</TextView>
</RelativeLayout>
+37
View File
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019, 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.
-
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/filter_button"
android:title="@string/filter_button_text" />
<item
android:id="@+id/menu_benchmark_mode"
android:checkable="true"
android:title="@string/menu_benchmark_mode_title"/>
<item
android:id="@+id/menu_headless"
android:checkable="true"
android:title="@string/menu_headless_title" />
<item
android:id="@+id/menu_run_samples"
android:title="@string/menu_run_samples_title"/>
</menu>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019, 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.
-
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019, 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.
-
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019, 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.
-
-->
<resources>
<color name="colorPrimary">#008FBE</color>
<color name="colorPrimaryDark">#333E47</color>
<color name="colorAccent">#F26B21</color>
</resources>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019, 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.
-
-->
<resources>
<color name="ic_launcher_background">#000000</color>
</resources>
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- 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.
-
-->
<resources>
<string name="app_name">Vulkan Samples</string>
<string name="channel_name">vkb_channel</string>
<string name="channel_desc">vkb_channel is a channel for the vulkan best practice application notifications</string>
<string name="native_lib_name">vulkan_samples</string>
<string name="permissions_text">Some permissions were not granted</string>
<string name="permissions_button">Grant Permissions</string>
<string name="menu_run_samples_title">Run All Samples</string>
<string name="open_file_with">Open File With</string>
<string name="menu_benchmark_mode_title">Benchmark Mode</string>
<string name="menu_headless_title">Headless</string>
<string name="filter_button_text">Filter</string>
</resources>
+39
View File
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019, 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.
-
-->
<resources>
<!-- Base application theme -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="buttonStyle">@style/ButtonStyle</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="Toolbar.TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
<item name="android:textSize">16dip</item>
</style>
<style name="ButtonStyle" parent="Widget.AppCompat.Button">
<item name="android:textAllCaps">false</item>
</style>
</resources>
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2019, 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.
-
-->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
+91
View File
@@ -0,0 +1,91 @@
# Copyright (c) 2020-2024, 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)
project(apps)
# Generate apps.cpp
set(APP_INFO_LIST)
set(SAMPLE_INCLUDE_FILES)
set(SAMPLE_INFO_LIST)
foreach(SAMPLE_ID ${TOTAL_SAMPLE_ID_LIST})
if ("${VKB_${SAMPLE_ID}}" AND TARGET ${SAMPLE_ID})
get_target_property(SAMPLE_CATEGORY ${SAMPLE_ID} SAMPLE_CATEGORY)
get_target_property(SAMPLE_AUTHOR ${SAMPLE_ID} SAMPLE_AUTHOR)
get_target_property(SAMPLE_NAME ${SAMPLE_ID} SAMPLE_NAME)
get_target_property(SAMPLE_DESCRIPTION ${SAMPLE_ID} SAMPLE_DESCRIPTION)
get_target_property(SAMPLE_TAGS ${SAMPLE_ID} SAMPLE_TAGS)
# Ensure we send in an empty C++ string as the vendor category, rather than a string with a space
set(INCLUDE_DIR ${SAMPLE_CATEGORY}/${SAMPLE_ID})
set(SAMPLE_TAGS_VECTOR)
list(JOIN SAMPLE_TAGS "\", \"" SAMPLE_TAGS_VECTOR)
list(APPEND SAMPLE_INCLUDE_FILES "#include \"${INCLUDE_DIR}/${SAMPLE_ID}.h\"")
list(APPEND SAMPLE_INFO_LIST "\tSampleInfo{\"${SAMPLE_ID}\", create_${SAMPLE_ID}, \"${SAMPLE_CATEGORY}\"\, \"${SAMPLE_AUTHOR}\"\, \"${SAMPLE_NAME}\"\, \"${SAMPLE_DESCRIPTION}\", {\"${SAMPLE_TAGS_VECTOR}\"}},")
list(APPEND APP_INFO_LIST "\tAppInfo{\"${SAMPLE_ID}\", create_${SAMPLE_ID}},")
endif()
endforeach()
list(JOIN SAMPLE_INCLUDE_FILES "\n" SAMPLE_INCLUDE_FILES)
list(JOIN SAMPLE_INFO_LIST "\n" SAMPLE_INFO_LIST)
list(JOIN APP_INFO_LIST "\n" APP_INFO_LIST)
configure_file(apps.cpp.in apps.cpp)
# Create apps library
set(SRC
apps.h
${CMAKE_CURRENT_BINARY_DIR}/apps.cpp
)
add_library(${PROJECT_NAME} STATIC ${SRC})
target_link_libraries(${PROJECT_NAME} PUBLIC framework)
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/samples)
# Link all samples
set(PROJECT_ID_LIST ${TOTAL_SAMPLE_ID_LIST})
foreach(ID ${PROJECT_ID_LIST})
if(TARGET ${ID})
get_target_property(TARGET_TYPE ${ID} TYPE)
if(TARGET_TYPE STREQUAL "OBJECT_LIBRARY" OR TARGET_TYPE STREQUAL "STATIC_LIBRARY")
target_link_libraries(${PROJECT_NAME} PUBLIC ${ID})
endif()
endif()
endforeach()
if (IOS)
target_link_libraries(${PROJECT_NAME} PRIVATE
"-framework UIKit"
"-framework Foundation"
"-framework CoreGraphics"
"-framework Metal"
"-framework QuartzCore"
"-framework IOKit"
"-framework IOSurface"
)
endif ()
+122
View File
@@ -0,0 +1,122 @@
/* Copyright (c) 2020-2024, 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 "apps.h"
@SAMPLE_INCLUDE_FILES@
namespace apps
{
std::vector<AppInfo> apps = {
@APP_INFO_LIST@
};
std::vector<SampleInfo> samples = {
@SAMPLE_INFO_LIST@
};
AppInfo *get_app(const std::string &id)
{
for (auto &app : apps)
{
if (app.id == id)
{
return &app;
}
}
return nullptr;
}
std::vector<AppInfo *> get_apps()
{
std::vector<AppInfo *> app_ptrs;
for (auto &app : apps)
{
app_ptrs.push_back(&app);
}
return app_ptrs;
}
std::vector<AppInfo *> get_samples(const std::vector<std::string> &categories, const std::vector<std::string> &tags)
{
std::vector<AppInfo *> app_ptrs;
for (auto &app : samples)
{
app_ptrs.push_back(&app);
}
// No filters
if (categories.empty() && tags.empty())
{
return app_ptrs;
}
std::vector<AppInfo *> filtered;
for (auto app : app_ptrs)
{
auto *sample = reinterpret_cast<SampleInfo *>(app);
bool selected = false;
// Sample is in one of the desired categories
for (auto &category : categories)
{
if (category == sample->category)
{
selected = true;
break;
}
}
// Sample has one or more of the desired tags
for (auto &tag : tags)
{
for (auto &s_tag : sample->tags)
{
if (s_tag == tag)
{
selected = true;
break;
}
}
}
if (selected)
{
filtered.push_back(app);
}
}
return filtered;
}
SampleInfo * get_sample(const std::string &id) {
for (auto& sample : samples) {
if (sample.id == id) {
return &sample;
}
}
return nullptr;
}
} // namespace apps
+98
View File
@@ -0,0 +1,98 @@
/* Copyright (c) 2020-2024, 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 <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "platform/application.h"
/*
*
* Vulkan Samples currently has two types of apps, Samples and Tests. These apps work from the same interface AppInfo.
* Samples and Tests are categorised into namespaces samples and tests respectively. Each name space has a method to retrieve
* the AppInfo interface version of the app (tests::get_apps, samples::get_apps).
*
*/
namespace apps
{
using CreateFunc = std::function<std::unique_ptr<vkb::Application>()>;
/*
* Apps - Used by Vulkan Samples to load a vkb::Applicaiton with the creation function (CreateFunc create).
*/
class AppInfo
{
public:
AppInfo(const std::string &id, const CreateFunc &create) :
id(id), create(create)
{}
std::string id;
CreateFunc create;
};
/*
* Samples - These are individual applications which show different usages and optimizations of the Vulkan API
*/
class SampleInfo : public AppInfo
{
public:
SampleInfo(const std::string &id, const CreateFunc &create, const std::string &category, const std::string &author, const std::string &name, const std::string &description, const std::vector<std::string> &tags = {}) :
AppInfo(id, create), category(category), author(author), name(name), description(description), tags(tags)
{}
std::string category;
std::string author;
std::string name;
std::string description;
std::vector<std::string> tags;
};
/**
* @brief Get a specific app
*
* @param id ID of a specific app
* @return const std::vector<AppInfo *>
*/
AppInfo *get_app(const std::string &id);
/**
* @brief Get all apps
*
* @return const std::vector<AppInfo *> A list of all apps
*/
std::vector<AppInfo *> get_apps();
/**
* @brief Get all samples
*
* @param categories If not empty the lists will include samples that match on of the categories requested
* @param tags If not empty the lists will include samples that match on of the tags requested
* @return std::vector<AppInfo *> A list of samples
*/
std::vector<AppInfo *> get_samples(const std::vector<std::string> &categories = {}, const std::vector<std::string> &tags = {});
SampleInfo *get_sample(const std::string &id);
} // namespace apps
+36
View File
@@ -0,0 +1,36 @@
/* Copyright (c) 2024, Holochip Inc.
*
* 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 <TargetConditionals.h>
#if TARGET_OS_IOS
#import <UIKit/UIKit.h>
#else
#include <AppKit/AppKit.h>
#endif
#if TARGET_OS_IOS
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
#else
@interface AppDelegate : NSResponder <NSApplicationDelegate>
@property (strong, nonatomic) NSWindow *window;
#endif
@end
+55
View File
@@ -0,0 +1,55 @@
/* Copyright (c) 2024, Holochip Inc.
*
* 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.
*/
#import "AppDelegate.h"
#if TARGET_OS_IOS
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
@end
#endif
+55
View File
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2024, Holochip Inc.
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.
-->
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleGetInfoString</key>
<string></string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string></string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>CFBundleName</key>
<string>vulkan samples</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>UIMainStoryboardFile</key>
<string>Storyboard</string>
<key>UILaunchStoryboardName</key>
<string>launch</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string></string>
</dict>
</plist>
+48
View File
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2024, Holochip Inc.
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.
-->
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" customClass="ViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc" customClass="VulkanView">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<connections>
<outlet property="vulkan_view" destination="5EZ-qb-Rvc" id="XCX-oU-713"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-218" y="4"/>
</scene>
</scenes>
</document>
+21
View File
@@ -0,0 +1,21 @@
/* Copyright (c) 2024, Holochip Inc.
*
* 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.
*/
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
+76
View File
@@ -0,0 +1,76 @@
/* Copyright (c) 2024, Holochip Inc.
*
* 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 "ViewController.h"
#include "ios/context.hpp"
#include "core/platform/entrypoint.hpp"
#include "platform/ios/ios_platform.h"
#include "platform/ios/ios_window.h"
int platform_main(const vkb::PlatformContext &);
@interface ViewController(){
CADisplayLink* _displayLink;
std::unique_ptr<vkb::PlatformContext> context;
vkb::IosPlatformContext* _context;
vkb::ExitCode _code;
}
@property (retain, nonatomic) IBOutlet VulkanView *vulkan_view;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Convert incoming args to "C" argc/argv strings
NSArray *args = [[NSProcessInfo processInfo] arguments];
const char** argv = (const char**) alloca(sizeof(char*) * args.count);
for(unsigned int i = 0; i < args.count; i++) {
NSString *s = args[i];
argv[i] = s.UTF8String;
}
self.vulkan_view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
context = create_platform_context((int)args.count, const_cast<char**>(argv));
_context = (vkb::IosPlatformContext*)context.get();
_context->view = self.vulkan_view;
_code = (vkb::ExitCode)platform_main(*context);
uint32_t fps = 60;
_displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderLoop)];
[_displayLink setPreferredFramesPerSecond:fps];
[_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode];
}
-(void) renderLoop {
if(!_displayLink.isPaused && [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
if(_code == vkb::ExitCode::Success) {
_code = ((vkb::IosPlatform*)_context->userPlatform)->main_loop_frame();
}
else {
// On ExitCode error, remove displayLink from run loop and terminate any active sample or batch run
[_displayLink invalidate];
((vkb::IosPlatform*)_context->userPlatform)->terminate(_code);
// Not typically allowed for iOS apps, but exit here given this is an Xcode-controlled dev application
exit(0);
}
}
}
@end
+50
View File
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2024, Holochip Inc.
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.
-->
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="48" y="-2"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
+58
View File
@@ -0,0 +1,58 @@
/* Copyright (c) 2019-2024, 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.
*/
#include "core/util/logging.hpp"
#include "platform/platform.h"
#include "../plugins/plugins.h"
#include <core/platform/entrypoint.hpp>
#include <filesystem/filesystem.hpp>
#include <TargetConditionals.h>
#import <Foundation/Foundation.h>
#import "AppDelegate.h"
#include "platform/ios/ios_platform.h"
#include "ios/context.hpp"
#undef CUSTOM_MAIN
# define CUSTOM_MAIN(context_name) \
int platform_main(const vkb::PlatformContext &); \
int main(int argc, char *argv[]) \
{ \
NSString * appDelegateClassName; \
@autoreleasepool { \
appDelegateClassName = NSStringFromClass([AppDelegate class]); \
return UIApplicationMain(argc, argv, nil, appDelegateClassName); \
} \
} \
int platform_main(const vkb::PlatformContext &context_name)
std::unique_ptr<vkb::IosPlatform> platform;
CUSTOM_MAIN(context)
{
vkb::filesystem::init_with_context(context);
platform = std::make_unique<vkb::IosPlatform>(context);
auto code = platform->initialize(plugins::get_all());
((vkb::IosPlatformContext*)&context)->userPlatform = platform.get();
return (int)code;
}
+73
View File
@@ -0,0 +1,73 @@
/* Copyright (c) 2019-2024, 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.
*/
#include "core/util/logging.hpp"
#include "platform/platform.h"
#include "plugins/plugins.h"
#include <core/platform/entrypoint.hpp>
#include <filesystem/filesystem.hpp>
#if defined(PLATFORM__MACOS)
# include <TargetConditionals.h>
#endif
#if defined(PLATFORM__ANDROID)
# include "platform/android/android_platform.h"
#elif defined(PLATFORM__WINDOWS)
# include "platform/windows/windows_platform.h"
#elif defined(PLATFORM__LINUX_D2D)
# include "platform/unix/unix_d2d_platform.h"
#elif defined(PLATFORM__LINUX) || defined(PLATFORM__MACOS) && !(TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE)
# include "platform/unix/unix_platform.h"
#elif defined(PLATFORM__MACOS) && (TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE)
# include "platform/ios/ios_platform.h"
#else
# error "Platform not supported"
#endif
CUSTOM_MAIN(context)
{
vkb::filesystem::init_with_context(context);
#if defined(PLATFORM__ANDROID)
vkb::AndroidPlatform platform{context};
#elif defined(PLATFORM__WINDOWS)
vkb::WindowsPlatform platform{context};
#elif defined(PLATFORM__LINUX_D2D)
vkb::UnixD2DPlatform platform{context};
#elif defined(PLATFORM__LINUX)
vkb::UnixPlatform platform{context, vkb::UnixType::Linux};
#elif defined(PLATFORM__MACOS) && !(TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE)
vkb::UnixPlatform platform{context, vkb::UnixType::Mac};
#elif (TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE)
vkb::IosPlatform platform{context};
#else
# error "Platform not supported"
#endif
auto code = platform.initialize(plugins::get_all());
if (code == vkb::ExitCode::Success)
{
code = platform.main_loop();
}
platform.terminate(code);
return 0;
}
+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
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

+128
View File
@@ -0,0 +1,128 @@
#[[
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.
]]
set(SCRIPT_DIR ${CMAKE_CURRENT_LIST_DIR})
function(add_android_package_project)
set(options)
set(oneValueArgs NAME JAVA_DIR RES_DIR MANIFEST_FILE)
set(multiValueArgs DEPENDS ASSET_DIRS)
cmake_parse_arguments(PARSE_ARGV 0 TARGET "${options}" "${oneValueArgs}" "${multiValueArgs}")
find_package(Gradle REQUIRED 4.10)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME})
project(${TARGET_NAME})
set(GRADLE_ANDROID_SCRIPT ${SCRIPT_DIR}/create_gradle_project.cmake)
if(NOT EXISTS ${GRADLE_ANDROID_SCRIPT})
message(FATAL_ERROR "No gradle android script exists at `${GRADLE_ANDROID_SCRIPT}`")
endif()
set(GRADLE_CONFIG_FILE ${SCRIPT_DIR}/template/gradle/build.gradle.in)
if(NOT EXISTS ${GRADLE_CONFIG_FILE})
message(FATAL_ERROR "No build.gradle.in template file exists at `${GRADLE_CONFIG_FILE}`")
endif()
set(JNI_LIBS_DIRS)
foreach(TARGET_DEPEND ${TARGET_DEPENDS})
if(TARGET ${TARGET_DEPEND})
get_target_property(BINARY_DIR ${TARGET_DEPEND} BINARY_DIR)
list(APPEND JNI_LIBS_DIRS ${BINARY_DIR}/lib/${CMAKE_BUILD_TYPE})
endif()
endforeach()
add_custom_command(
OUTPUT
gen.gradle.stamp
DEPENDS
${GRADLE_CONFIG_FILE}
${GRADLE_ANDROID_SCRIPT}
COMMAND
${CMAKE_COMMAND}
-DPROJECT_NAME=${CMAKE_PROJECT_NAME}
-DANDROID_API=${CMAKE_ANDROID_API}
-DARCH_ABI=${CMAKE_ANDROID_ARCH_ABI}
-DANDROID_MANIFEST=${TARGET_MANIFEST_FILE}
-DJAVA_DIRS=${TARGET_JAVA_DIR}
-DRES_DIRS=${TARGET_RES_DIR}
-DJNI_LIBS_DIRS=${JNI_LIBS_DIRS}
-DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
-DASSET_DIRS=${TARGET_ASSET_DIRS}
-P ${GRADLE_ANDROID_SCRIPT}
COMMAND
${CMAKE_COMMAND} -E touch gen.gradle.stamp
COMMENT
"Generate android gradle project"
WORKING_DIRECTORY
${TARGET_NAME}
VERBATIM)
add_custom_command(
OUTPUT
bld.gradle.stamp
DEPENDS
gen.gradle.stamp
COMMAND
${GRADLE_EXECUTABLE} assemble --no-daemon
COMMAND
${CMAKE_COMMAND} -E touch bld.gradle.stamp
COMMENT
"Build android gradle project"
WORKING_DIRECTORY
${TARGET_NAME}
VERBATIM)
add_custom_target(${TARGET_NAME} ALL
DEPENDS
bld.gradle.stamp
${TARGET_DEPENDS})
endfunction()
function(android_sync_folder)
set(options)
set(oneValueArgs PATH)
set(multiValueArgs)
cmake_parse_arguments(PARSE_ARGV 0 TARGET "${options}" "${oneValueArgs}" "${multiValueArgs}")
get_filename_component(FOLDER_NAME "${TARGET_PATH}" NAME)
set(SYNC_COMMAND ${CMAKE_COMMAND}
-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}
-DFOLDER_DIR=${TARGET_PATH}/.
-DDEVICE_DIR=/sdcard/Android/data/com.khronos.${PROJECT_NAME}/files/${FOLDER_NAME}/
-P "${SCRIPT_DIR}/android_sync_folder.cmake")
add_custom_target(
sync.${FOLDER_NAME}.stamp
COMMAND
${SYNC_COMMAND}
COMMENT
"Update ${FOLDER_NAME} in external storage"
VERBATIM)
add_dependencies(${PROJECT_NAME} sync.${FOLDER_NAME}.stamp)
endfunction()
+97
View File
@@ -0,0 +1,97 @@
#[[
Copyright (c) 2019-2024, 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.
]]
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
${CMAKE_MODULE_PATH}/module)
set(FOLDER_DIR ${FOLDER_DIR})
set(DEVICE_DIR ${DEVICE_DIR})
find_package(Adb 1.0.39 REQUIRED)
# Sync files to temporary directory
get_filename_component(DIR_PATH "${FOLDER_DIR}" DIRECTORY)
get_filename_component(DIR_NAME "${DIR_PATH}" NAME)
set(TEMP_DIR "/data/local/tmp/${DIR_NAME}")
# Ensure that directory exists in the target
set(ADB_COMMAND ${ADB_EXECUTABLE} shell mkdir -p ${TEMP_DIR})
execute_process(
COMMAND
${ADB_COMMAND})
set(ADB_COMMAND ${ADB_EXECUTABLE} push --sync ${FOLDER_DIR} ${TEMP_DIR})
execute_process(
COMMAND
${ADB_COMMAND}
RESULT_VARIABLE
ret_var
OUTPUT_VARIABLE
ret_msg
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT "${ret_var}" STREQUAL "0")
message(WARNING "Could not sync ${FOLDER_DIR} to temp dir:\n${ret_msg}")
else()
message(STATUS "Updated ${FOLDER_DIR} to ${TEMP_DIR}:\n${ret_msg}")
endif()
# Copy to final device destination
get_filename_component(DIR_PATH "${DEVICE_DIR}" DIRECTORY)
# Ensure that directory exists in the target
set(ADB_COMMAND ${ADB_EXECUTABLE} shell mkdir -p ${DIR_PATH})
execute_process(
COMMAND
${ADB_COMMAND})
set(ADB_COMMAND ${ADB_EXECUTABLE} shell cp -r ${TEMP_DIR} ${DIR_PATH})
execute_process(
COMMAND
${ADB_COMMAND}
RESULT_VARIABLE
ret_var
OUTPUT_VARIABLE
ret_msg
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT "${ret_var}" STREQUAL "0")
message(WARNING "Could not copy ${FOLDER_DIR} to final dir:\n${ret_msg}")
else()
message(STATUS "Copied ${TEMP_DIR} to ${DIR_PATH}:\n${ret_msg}")
endif()
execute_process(
COMMAND
${ADB_COMMAND})
# Ensure file permissions
set(ADB_COMMAND ${ADB_EXECUTABLE} shell chmod 777 -R ${DIR_PATH})
execute_process(
COMMAND
${ADB_COMMAND})
+79
View File
@@ -0,0 +1,79 @@
# 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.
#
# check whether need to link atomic library explicitly
INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckLibraryExists)
if(NOT DEFINED VULKAN_COMPILER_IS_GCC_COMPATIBLE)
if(CMAKE_COMPILER_IS_GNUCXX)
set(VULKAN_COMPILER_IS_GCC_COMPATIBLE ON)
elseif( MSVC )
set(VULKAN_COMPILER_IS_GCC_COMPATIBLE OFF)
elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
set(VULKAN_COMPILER_IS_GCC_COMPATIBLE ON)
elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" )
set(VULKAN_COMPILER_IS_GCC_COMPATIBLE ON)
endif()
endif()
# Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics.
function(check_working_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
std::atomic<int> x;
std::atomic<short> y;
std::atomic<char> z;
int main() {
++z;
++y;
return ++x;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics)
function(check_working_cxx_atomics64 varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
#include <cstdint>
std::atomic<uint64_t> x (0);
int main() {
uint64_t i = x.load(std::memory_order_relaxed);
(void)i;
return 0;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics64)
set(NEED_LINK_ATOMIC OFF CACHE BOOL "whether need to link against atomic library")
if(VULKAN_COMPILER_IS_GCC_COMPATIBLE)
# check if non-64-bit atomics work without the library.
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
# check 64-bit atomics work without the library.
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
if (NOT HAVE_CXX_ATOMICS_WITHOUT_LIB OR NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
set(NEED_LINK_ATOMIC ON CACHE BOOL "whether need to link to atomic library" FORCE)
endif()
endif()

Some files were not shown because too many files have changed in this diff Show More