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
+89
View File
@@ -0,0 +1,89 @@
////
- Copyright (c) 2019-2023, The Khronos Group
-
- 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.
-
////
// NOTE: Remove the following comment block for the actual readme of your sample -->
////
This is a template for the sample's readme. Every new sample should come with a readme that contains at least a short tutorial that accompanies the code of the example.
Readmes are written in Asciidoc (see https://asciidoc.org/).
You can freely choose how to structure it, but it should always contain an overview and conclusion paragraph.
The readme can (and most often should) show code from along with an explanation. Code in asciidoc can be rendered with syntax highlighting using the following syntax:
[,cpp]
----
void main() {
std::cout << "Hello World";
}
----
or
[,glsl]
----
void main() {
gl_color = vec4(1.0f);
}
----
Ideally it also contains an image of how the sample is supposed to look.
For an example you can take a look at the readme's of existing samples, e.g. https://raw.githubusercontent.com/KhronosGroup/Vulkan-Samples/main/samples/extensions/descriptor_indexing/README.adoc
////
= Sample name
////
The following block adds linkage to this repo in the Vulkan docs site project. It's only visible if the file is viewed via the Antora framework.
////
ifdef::site-gen-antora[]
TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/PUT_SAMPLE_PATH_HERE[Khronos Vulkan samples github repository].
endif::[]
== Overview
////
This chapter should contain an overview of what this sample is trying to achieve. If extensions are used, this chapter should also list those.
The following chapters get into the details on how the sample is working, what features are used, etc.
The chapter itself can be structured by using sub paragraphs, e.g.:
# Feature description
# Enabling extensions
# etc.
////
== Conclusion
////
The tutorial should end with a conclusion chapter that recaps the tutorial and (if applicable) talks about pros and cons of the features demonstrated in this sample
////
////
NOTE: Please also add a link to the new samples' README.adoc to the file located in ./antora/modules/ROOT/nav.adoc
THis is necessary to have the sample show up on the build for the docs site under https://docs.vulkan.org
////
@@ -0,0 +1,84 @@
plugins {
id 'com.android.application'
}
ext.vvl_version='1.4.321.0'
apply from: "./download_vvl.gradle"
android {
ndkVersion '28.2.13676358'
compileSdk 35
defaultConfig {
applicationId 'com.khronos.vulkan_samples'
namespace "com.khronos.vulkan_samples"
@MIN_SDK_VERSION@
targetSdk 35
versionCode 1
versionName "1.0"
externalNativeBuild {
@CMAKE_ARGUMENTS@
}
}
buildTypes {
debug {
debuggable true
jniDebuggable true
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
signingConfig debug.signingConfig
}
applicationVariants.all{variant ->
variant.outputs.each{output->
def tempName = output.outputFile.name
tempName = tempName.replace("app-", "vulkan_samples-")
output.outputFileName = tempName
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
sourceSets {
main {
@ASSETS_SRC_DIRS@
@RES_SRC_DIRS@
@JAVA_SRC_DIRS@
@JNI_LIBS_SRC_DIRS@
@MANIFEST_FILE@
}
}
externalNativeBuild {
cmake {
version "3.22.1"
@CMAKE_PATH@
}
}
lint {
abortOnError false
checkReleaseBuilds false
}
buildFeatures {
viewBinding true
prefab true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
implementation 'androidx.core:core:1.15.0'
implementation 'androidx.games:games-activity:3.0.5'
}
@@ -0,0 +1,8 @@
plugins {
id 'com.android.application' version '8.7.2' apply false
id 'com.android.library' version '8.7.2' apply false
}
tasks.register('clean', Delete) {
delete rootProject.layout.buildDirectory
}
@@ -0,0 +1,81 @@
apply plugin: 'com.android.application'
/*
* Copyright (c) 2022-2024, The Android Open Source Project.
*
* 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.
*
*/
/*
* Download validation layer binary release zip file from Khronos github repo
* https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases
*
* To use this script, add the following to your module's build.gradle:
* ext.vvl_version='your-new-version'
* apply from: "${PATH-TO-THIS}/download_vvl.gradle"
* To update to a new version:
* - change the ext.vvl_version to a new version string.
* - delete directory pointed by ${VVL_JNILIB_DIR}.
* - sync gradle script in IDE and rebuild project.
*
* Note: binary release can also be manually downloaded and put it into
* the default jniLibs directory at app/src/main/jniLibs.
*/
// get the validation layer version.
def VVL_VER = "1.4.321.0"
if (ext.has("vvl_version")) {
VVL_VER = ext.vvl_version
}
// declare local variables shared between downloading and unzipping.
def VVL_SITE ="https://github.com/KhronosGroup/Vulkan-ValidationLayers"
def VVL_LIB_ROOT= rootDir.absolutePath.toString() + "/layerLib"
def VVL_JNILIB_DIR="${VVL_LIB_ROOT}/jniLibs"
def VVL_SO_NAME = "libVkLayer_khronos_validation.so"
// download the release zip file to ${VVL_LIB_ROOT}/
task download {
def VVL_ZIP_NAME = "releases/download/vulkan-sdk-${VVL_VER}/android-binaries-${VVL_VER}.zip"
mkdir "${VVL_LIB_ROOT}"
def f = new File("${VVL_LIB_ROOT}/android-binaries-${VVL_VER}.zip")
new URL("${VVL_SITE}/${VVL_ZIP_NAME}")
.withInputStream { i -> f.withOutputStream { it << i } }
}
// unzip the downloaded VVL zip archive to the ${VVL_JNILIB_DIR} for APK packaging.
task unzip(dependsOn: download, type: Copy) {
from zipTree(file("${VVL_LIB_ROOT}/android-binaries-${VVL_VER}.zip"))
into file("${VVL_JNILIB_DIR}")
}
android.sourceSets.main.jniLibs {
srcDirs += ["${VVL_JNILIB_DIR}/android-binaries-${VVL_VER}"]
}
// add vvl download as an application dependency.
dependencies {
def ARM64_VVL_FILE = "${VVL_JNILIB_DIR}/arm64-v8a/${VVL_SO_NAME}"
if(!file("${ARM64_VVL_FILE}").exists()) {
implementation files("${ARM64_VVL_FILE}") {
builtBy 'unzip'
}
}
}
project.afterEvaluate{
project.getTasks().getByName("mergeDebugJniLibFolders").dependsOn(unzip)
project.getTasks().getByName("mergeReleaseJniLibFolders").dependsOn(unzip)
}
Binary file not shown.
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
@@ -0,0 +1,7 @@
android.useAndroidX=true
android.enableJetifier=false
org.gradle.parallel=true
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
org.gradle.caching=true
android.prefabVersion=2.0.0
+252
View File
@@ -0,0 +1,252 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# 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
#
# https://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.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
+94
View File
@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@@ -0,0 +1,16 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "@PROJECT_NAME@"
include ':app'
@@ -0,0 +1,33 @@
# 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.
#
get_filename_component(FOLDER_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
get_filename_component(PARENT_DIR ${CMAKE_CURRENT_LIST_DIR} PATH)
get_filename_component(CATEGORY_NAME ${PARENT_DIR} NAME)
add_sample(
ID ${FOLDER_NAME}
CATEGORY ${CATEGORY_NAME}
AUTHOR "Khronos"
NAME "@SAMPLE_NAME@"
DESCRIPTION "Sample description"
# Important note: Shaders are compiled offline via CMake, so all shaders
# used by this sample need to be put here
# The framework also supports HLSL (SHADER_FILES_HLSL) and Slang (SHADER_FILES_SLANG)
SHADER_FILES_GLSL
"triangle.vert"
"triangle.frag")
@@ -0,0 +1,64 @@
/* 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.
*/
#include "@SAMPLE_NAME_FILE@.h"
#include "common/vk_common.h"
#include "gltf_loader.h"
#include "gui.h"
#include "filesystem/legacy.h"
#include "platform/platform.h"
#include "rendering/subpasses/forward_subpass.h"
#include "stats/stats.h"
@SAMPLE_NAME@::@SAMPLE_NAME@()
{
}
bool @SAMPLE_NAME@::prepare(const vkb::ApplicationOptions &options)
{
if (!VulkanSample::prepare(options))
{
return false;
}
// Load a scene from the assets folder
load_scene("scenes/sponza/Sponza01.gltf");
// Attach a move script to the camera component in the scene
auto &camera_node = vkb::add_free_camera(get_scene(), "main_camera", get_render_context().get_surface_extent());
auto camera = &camera_node.get_component<vkb::sg::Camera>();
// Example Scene Render Pipeline
vkb::ShaderSource vert_shader("base.vert.spv");
vkb::ShaderSource frag_shader("base.frag.spv");
auto scene_subpass = std::make_unique<vkb::ForwardSubpass>(get_render_context(), std::move(vert_shader), std::move(frag_shader), get_scene(), *camera);
auto render_pipeline = std::make_unique<vkb::RenderPipeline>();
render_pipeline->add_subpass(std::move(scene_subpass));
set_render_pipeline(std::move(render_pipeline));
// Add a GUI with the stats you want to monitor
get_stats().request_stats({/*stats you require*/});
create_gui(*window, &get_stats());
return true;
}
std::unique_ptr<vkb::VulkanSampleC> create_@SAMPLE_NAME_FILE@()
{
return std::make_unique<@SAMPLE_NAME@>();
}
+34
View File
@@ -0,0 +1,34 @@
/* 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.
*/
#pragma once
#include "rendering/render_pipeline.h"
#include "scene_graph/components/camera.h"
#include "vulkan_sample.h"
class @SAMPLE_NAME@ : public vkb::VulkanSampleC
{
public:
@SAMPLE_NAME@();
virtual bool prepare(const vkb::ApplicationOptions &options) override;
virtual ~@SAMPLE_NAME@() = default;
};
std::unique_ptr<vkb::VulkanSampleC> create_@SAMPLE_NAME_FILE@();
@@ -0,0 +1,33 @@
# Copyright (c) 2023-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.
#
get_filename_component(FOLDER_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
get_filename_component(PARENT_DIR ${CMAKE_CURRENT_LIST_DIR} PATH)
get_filename_component(CATEGORY_NAME ${PARENT_DIR} NAME)
add_sample(
ID ${FOLDER_NAME}
CATEGORY ${CATEGORY_NAME}
AUTHOR "<<Contributor>>"
NAME "@SAMPLE_NAME@"
DESCRIPTION "Sample description"
# Important note: Shaders are compiled offline via CMake, so all shaders
# used by this sample need to be put here
# The framework also supports HLSL (SHADER_FILES_HLSL) and Slang (SHADER_FILES_SLANG)
SHADER_FILES_GLSL
"triangle.vert"
"triangle.frag")
@@ -0,0 +1,174 @@
/* Copyright (c) 2024-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.
*/
#include "@SAMPLE_NAME_FILE@.h"
@SAMPLE_NAME@::@SAMPLE_NAME@()
{
}
@SAMPLE_NAME@::~@SAMPLE_NAME@()
{
if (has_device())
{
vkDestroyPipeline(get_device().get_handle(), sample_pipeline, nullptr);
vkDestroyPipelineLayout(get_device().get_handle(), sample_pipeline_layout, nullptr);
}
}
bool @SAMPLE_NAME@::prepare(const vkb::ApplicationOptions &options)
{
if (!ApiVulkanSample::prepare(options))
{
return false;
}
prepare_pipelines();
build_command_buffers();
prepared = true;
return true;
}
void @SAMPLE_NAME@::prepare_pipelines()
{
// Create a blank pipeline layout.
// We are not binding any resources to the pipeline in this sample.
VkPipelineLayoutCreateInfo layout_info = vkb::initializers::pipeline_layout_create_info(nullptr, 0);
VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &layout_info, nullptr, &sample_pipeline_layout));
VkPipelineVertexInputStateCreateInfo vertex_input = vkb::initializers::pipeline_vertex_input_state_create_info();
// Specify we will use triangle lists to draw geometry.
VkPipelineInputAssemblyStateCreateInfo input_assembly = vkb::initializers::pipeline_input_assembly_state_create_info(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE);
// Specify rasterization state.
VkPipelineRasterizationStateCreateInfo raster = vkb::initializers::pipeline_rasterization_state_create_info(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE);
// Our attachment will write to all color channels, but no blending is enabled.
VkPipelineColorBlendAttachmentState blend_attachment = vkb::initializers::pipeline_color_blend_attachment_state(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, VK_FALSE);
VkPipelineColorBlendStateCreateInfo blend = vkb::initializers::pipeline_color_blend_state_create_info(1, &blend_attachment);
// We will have one viewport and scissor box.
VkPipelineViewportStateCreateInfo viewport = vkb::initializers::pipeline_viewport_state_create_info(1, 1);
// Enable depth testing (using reversed depth-buffer for increased precision).
VkPipelineDepthStencilStateCreateInfo depth_stencil = vkb::initializers::pipeline_depth_stencil_state_create_info(VK_TRUE, VK_TRUE, VK_COMPARE_OP_GREATER);
// No multisampling.
VkPipelineMultisampleStateCreateInfo multisample = vkb::initializers::pipeline_multisample_state_create_info(VK_SAMPLE_COUNT_1_BIT);
// Specify that these states will be dynamic, i.e. not part of pipeline state object.
std::array<VkDynamicState, 2> dynamics{VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
VkPipelineDynamicStateCreateInfo dynamic = vkb::initializers::pipeline_dynamic_state_create_info(dynamics.data(), vkb::to_u32(dynamics.size()));
// Load our SPIR-V shaders.
std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages{};
// Vertex stage of the pipeline
shader_stages[0] = load_shader("triangle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shader_stages[1] = load_shader("triangle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// We need to specify the pipeline layout and the render pass description up front as well.
VkGraphicsPipelineCreateInfo pipeline_create_info = vkb::initializers::pipeline_create_info(sample_pipeline_layout, render_pass);
pipeline_create_info.stageCount = vkb::to_u32(shader_stages.size());
pipeline_create_info.pStages = shader_stages.data();
pipeline_create_info.pVertexInputState = &vertex_input;
pipeline_create_info.pInputAssemblyState = &input_assembly;
pipeline_create_info.pRasterizationState = &raster;
pipeline_create_info.pColorBlendState = &blend;
pipeline_create_info.pMultisampleState = &multisample;
pipeline_create_info.pViewportState = &viewport;
pipeline_create_info.pDepthStencilState = &depth_stencil;
pipeline_create_info.pDynamicState = &dynamic;
VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &pipeline_create_info, nullptr, &sample_pipeline));
}
void @SAMPLE_NAME@::build_command_buffers()
{
VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info();
// Clear color and depth values.
VkClearValue clear_values[2];
clear_values[0].color = {{0.0f, 0.0f, 0.0f, 0.0f}};
clear_values[1].depthStencil = {0.0f, 0};
// Begin the render pass.
VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info();
render_pass_begin_info.renderPass = render_pass;
render_pass_begin_info.renderArea.offset.x = 0;
render_pass_begin_info.renderArea.offset.y = 0;
render_pass_begin_info.renderArea.extent.width = width;
render_pass_begin_info.renderArea.extent.height = height;
render_pass_begin_info.clearValueCount = 2;
render_pass_begin_info.pClearValues = clear_values;
for (int32_t i = 0; i < draw_cmd_buffers.size(); ++i)
{
auto cmd = draw_cmd_buffers[i];
// Begin command buffer.
vkBeginCommandBuffer(cmd, &command_buffer_begin_info);
// Set framebuffer for this command buffer.
render_pass_begin_info.framebuffer = framebuffers[i];
// We will add draw commands in the same command buffer.
vkCmdBeginRenderPass(cmd, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
// Bind the graphics pipeline.
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, sample_pipeline);
// Set viewport dynamically
VkViewport viewport = vkb::initializers::viewport(static_cast<float>(width), static_cast<float>(height), 0.0f, 1.0f);
vkCmdSetViewport(cmd, 0, 1, &viewport);
// Set scissor dynamically
VkRect2D scissor = vkb::initializers::rect2D(width, height, 0, 0);
vkCmdSetScissor(cmd, 0, 1, &scissor);
// Draw three vertices with one instance.
vkCmdDraw(cmd, 3, 1, 0, 0);
// Draw user interface.
draw_ui(draw_cmd_buffers[i]);
// Complete render pass.
vkCmdEndRenderPass(cmd);
// Complete the command buffer.
VK_CHECK(vkEndCommandBuffer(cmd));
}
}
void @SAMPLE_NAME@::render(float delta_time)
{
if (!prepared)
{
return;
}
ApiVulkanSample::prepare_frame();
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer];
VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE));
ApiVulkanSample::submit_frame();
}
std::unique_ptr<vkb::VulkanSampleC> create_@SAMPLE_NAME_FILE@()
{
return std::make_unique<@SAMPLE_NAME@>();
}
@@ -0,0 +1,42 @@
/* Copyright (c) 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 "api_vulkan_sample.h"
class @SAMPLE_NAME@ : public ApiVulkanSample
{
public:
@SAMPLE_NAME@();
virtual ~@SAMPLE_NAME@();
// Create pipeline
void prepare_pipelines();
// Override basic framework functionality
void build_command_buffers() override;
void render(float delta_time) override;
bool prepare(const vkb::ApplicationOptions &options) override;
private:
// Sample specific data
VkPipeline sample_pipeline{};
VkPipelineLayout sample_pipeline_layout{};
};
std::unique_ptr<vkb::VulkanSampleC> create_@SAMPLE_NAME_FILE@();