aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Thomson <paulthomson@google.com>2022-02-08 14:31:07 +0000
committerPaul Thomson <paulthomson@google.com>2022-02-08 14:31:07 +0000
commit3f8fbfe46bdb1dd1526687a84c644c1b2846a636 (patch)
tree7bf7238d34d1cdf3671a43fe4147a53606453504
parentf3b1d8fd9a3dfb99df5b8ba7900b3493ee0329a8 (diff)
parent615ab4863f7d2e31d3037d0c6a0f641fd6fc0d07 (diff)
downloadamber-android13-qpr2-s11-release.tar.gz
Merge commit '615ab4863f7d2e31d3037d0c6a0f641fd6fc0d07' into mastert_frc_odp_330442040t_frc_odp_330442000t_frc_con_330443020t_frc_cbr_330443000t_frc_ase_330444010t_frc_art_330443060android-13.0.0_r83android-13.0.0_r82android-13.0.0_r81android-13.0.0_r80android-13.0.0_r79android-13.0.0_r78android-13.0.0_r77android-13.0.0_r76android-13.0.0_r75android-13.0.0_r74android-13.0.0_r73android-13.0.0_r72android-13.0.0_r71android-13.0.0_r70android-13.0.0_r69android-13.0.0_r68android-13.0.0_r67android-13.0.0_r66android-13.0.0_r65android-13.0.0_r64android-13.0.0_r63android-13.0.0_r62android-13.0.0_r61android-13.0.0_r60android-13.0.0_r59android-13.0.0_r58android-13.0.0_r57android-13.0.0_r56android-13.0.0_r55android-13.0.0_r54android-13.0.0_r53android-13.0.0_r52android-13.0.0_r51android-13.0.0_r50android-13.0.0_r49android-13.0.0_r48android-13.0.0_r47android-13.0.0_r46android-13.0.0_r45android-13.0.0_r44android-13.0.0_r43android-13.0.0_r42android-13.0.0_r41android-13.0.0_r40android-13.0.0_r39android-13.0.0_r38android-13.0.0_r37android-13.0.0_r36android-13.0.0_r35android-13.0.0_r34android-13.0.0_r33android-13.0.0_r32android-13.0.0_r30android-13.0.0_r29android-13.0.0_r28android-13.0.0_r27android-13.0.0_r24android-13.0.0_r23android-13.0.0_r22android-13.0.0_r21android-13.0.0_r20android-13.0.0_r19android-13.0.0_r18android-13.0.0_r17android-13.0.0_r16aml_uwb_331910010aml_uwb_331820070aml_uwb_331613010aml_uwb_331611010aml_uwb_331410010aml_uwb_331310030aml_uwb_331115000aml_uwb_331015040aml_uwb_330810010aml_tz4_332714070aml_tz4_332714050aml_tz4_332714010aml_tz4_331910000aml_tz4_331314030aml_tz4_331314020aml_tz4_331314010aml_tz4_331012050aml_tz4_331012040aml_tz4_331012000aml_go_wif_330911000aml_go_uwb_330912000aml_go_tz4_330912000aml_go_tet_330914010aml_go_swc_330913000aml_go_sta_330911000aml_go_sdk_330810000aml_go_sch_330911000aml_go_res_330912000aml_go_per_330912000aml_go_odp_330913000aml_go_odp_330912000aml_go_neu_330912000aml_go_net_330913000aml_go_mpr_330912000aml_go_ase_330913000aml_go_ads_330915100aml_go_ads_330915000aml_go_ads_330913000aml_go_adb_330913000aml_ase_331311020aml_ase_331112000aml_ase_331011020aml_ads_331920180aml_ads_331814200aml_ads_331710270aml_ads_331611190aml_ads_331511020aml_ads_331418080aml_ads_331131000android13-qpr3-s9-releaseandroid13-qpr3-s8-releaseandroid13-qpr3-s7-releaseandroid13-qpr3-s6-releaseandroid13-qpr3-s5-releaseandroid13-qpr3-s4-releaseandroid13-qpr3-s3-releaseandroid13-qpr3-s2-releaseandroid13-qpr3-s14-releaseandroid13-qpr3-s13-releaseandroid13-qpr3-s12-releaseandroid13-qpr3-s11-releaseandroid13-qpr3-s10-releaseandroid13-qpr3-s1-releaseandroid13-qpr3-releaseandroid13-qpr3-c-s8-releaseandroid13-qpr3-c-s7-releaseandroid13-qpr3-c-s6-releaseandroid13-qpr3-c-s5-releaseandroid13-qpr3-c-s4-releaseandroid13-qpr3-c-s3-releaseandroid13-qpr3-c-s2-releaseandroid13-qpr3-c-s12-releaseandroid13-qpr3-c-s11-releaseandroid13-qpr3-c-s10-releaseandroid13-qpr3-c-s1-releaseandroid13-qpr2-s9-releaseandroid13-qpr2-s8-releaseandroid13-qpr2-s7-releaseandroid13-qpr2-s6-releaseandroid13-qpr2-s5-releaseandroid13-qpr2-s3-releaseandroid13-qpr2-s2-releaseandroid13-qpr2-s12-releaseandroid13-qpr2-s11-releaseandroid13-qpr2-s10-releaseandroid13-qpr2-s1-releaseandroid13-qpr2-releaseandroid13-qpr2-b-s1-releaseandroid13-qpr1-s8-releaseandroid13-qpr1-s7-releaseandroid13-qpr1-s6-releaseandroid13-qpr1-s5-releaseandroid13-qpr1-s4-releaseandroid13-qpr1-s3-releaseandroid13-qpr1-s2-releaseandroid13-qpr1-s1-releaseandroid13-qpr1-releaseandroid13-mainline-uwb-releaseandroid13-mainline-tzdata4-releaseandroid13-mainline-go-wifi-releaseandroid13-mainline-go-uwb-releaseandroid13-mainline-go-tzdata4-releaseandroid13-mainline-go-tethering-releaseandroid13-mainline-go-sdkext-releaseandroid13-mainline-go-scheduling-releaseandroid13-mainline-go-resolv-releaseandroid13-mainline-go-permission-releaseandroid13-mainline-go-os-statsd-releaseandroid13-mainline-go-odp-releaseandroid13-mainline-go-neuralnetworks-releaseandroid13-mainline-go-networking-releaseandroid13-mainline-go-mediaprovider-releaseandroid13-mainline-go-media-swcodec-releaseandroid13-mainline-go-appsearch-releaseandroid13-mainline-go-adservices-releaseandroid13-mainline-go-adbd-releaseandroid13-mainline-appsearch-releaseandroid13-mainline-adservices-releaseandroid13-frc-odp-releaseandroid13-frc-conscrypt-releaseandroid13-frc-cellbroadcast-releaseandroid13-frc-art-releaseandroid13-devandroid13-d4-s2-releaseandroid13-d4-s1-releaseandroid13-d4-releaseandroid13-d3-s1-releaseandroid13-d2-releaseaml_tz4_332714010
Conflicts: samples/Android.mk Bug: b/201652781 Change-Id: Ia48f5389d9cde2b0730767e215d86e28cced7da6
-rw-r--r--.gitignore5
-rw-r--r--CMakeLists.txt4
-rw-r--r--DEPS35
-rw-r--r--android_gradle/app/build.gradle44
-rw-r--r--android_gradle/app/src/androidTest/java/com/google/amber/AmberLauncher.java2
-rw-r--r--android_gradle/app/src/main/AndroidManifest.xml1
-rw-r--r--android_gradle/app/src/main/java/com/google/amber/Amber.java2
-rw-r--r--android_gradle/build.gradle13
-rw-r--r--android_gradle/gradle.properties2
-rw-r--r--android_gradle/gradle/wrapper/gradle-wrapper.jarbin54329 -> 59203 bytes
-rw-r--r--android_gradle/gradle/wrapper/gradle-wrapper.properties6
-rw-r--r--android_gradle/settings.gradle7
-rw-r--r--docs/amber_script.md114
-rw-r--r--docs/debugger.md6
-rw-r--r--samples/CMakeLists.txt8
-rw-r--r--samples/amber.cc8
-rw-r--r--samples/android_helper.cc (renamed from samples/android_main.cc)18
-rw-r--r--samples/config_helper_vulkan.cc98
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/amberscript/parser.cc114
-rw-r--r--src/amberscript/parser.h2
-rw-r--r--src/amberscript/parser_bind_test.cc127
-rw-r--r--src/amberscript/parser_blend_test.cc140
-rw-r--r--src/amberscript/parser_pipeline_test.cc82
-rw-r--r--src/buffer.h4
-rw-r--r--src/command_data.cc150
-rw-r--r--src/command_data.h8
-rw-r--r--src/pipeline.cc12
-rw-r--r--src/pipeline.h9
-rw-r--r--src/pipeline_data.h7
-rw-r--r--src/script.cc16
-rw-r--r--src/vulkan/CMakeLists.txt9
-rw-r--r--src/vulkan/buffer_backed_descriptor.cc92
-rw-r--r--src/vulkan/buffer_backed_descriptor.h21
-rw-r--r--src/vulkan/buffer_descriptor.cc106
-rw-r--r--src/vulkan/buffer_descriptor.h10
-rw-r--r--src/vulkan/command_buffer.cc1
-rw-r--r--src/vulkan/descriptor.h7
-rw-r--r--src/vulkan/device.cc201
-rw-r--r--src/vulkan/engine_vulkan.cc7
-rw-r--r--src/vulkan/frame_buffer.cc66
-rw-r--r--src/vulkan/frame_buffer.h3
-rw-r--r--src/vulkan/graphics_pipeline.cc42
-rw-r--r--src/vulkan/graphics_pipeline.h4
-rw-r--r--src/vulkan/image_descriptor.cc99
-rw-r--r--src/vulkan/image_descriptor.h11
-rw-r--r--src/vulkan/index_buffer.cc8
-rw-r--r--src/vulkan/pipeline.cc99
-rw-r--r--src/vulkan/pipeline.h13
-rw-r--r--src/vulkan/resource.h12
-rw-r--r--src/vulkan/transfer_buffer.cc14
-rw-r--r--src/vulkan/transfer_buffer.h13
-rw-r--r--src/vulkan/transfer_image.cc8
-rw-r--r--src/vulkan/transfer_image.h4
-rw-r--r--src/vulkan/vertex_buffer.cc5
-rw-r--r--tests/cases/compute_one_buffer_in_multiple_bindings.amber94
-rw-r--r--tests/cases/debugger_hlsl_basic_compute.amber2
-rw-r--r--tests/cases/debugger_hlsl_basic_vertex.amber6
-rw-r--r--tests/cases/debugger_hlsl_function_call.amber2
-rw-r--r--tests/cases/debugger_hlsl_shadowed_vars.amber7
-rw-r--r--tests/cases/debugger_spirv_line_stepping.amber6
-rw-r--r--tests/cases/draw_rect_blend.amber46
-rw-r--r--tests/cases/float16.amber4
-rw-r--r--tests/cases/multisample_resolve.amber50
-rw-r--r--tests/cases/tessellation_isolines.amber130
-rwxr-xr-xtests/run_tests.py2
-rw-r--r--third_party/CMakeLists.txt41
-rwxr-xr-xtools/roll-all2
68 files changed, 1901 insertions, 395 deletions
diff --git a/.gitignore b/.gitignore
index d5f3eb0..e847034 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@ third_party/swiftshader
third_party/vulkan-headers
third_party/vulkan-loader
third_party/vulkan-validationlayers/
+third_party/robin-hood-hashing
.vs
*.pyc
@@ -25,5 +26,5 @@ third_party/vulkan-validationlayers/
[._]*.s[a-w][a-z]
# C-Lion
-.idea
-cmake-build-debug
+.idea/
+cmake-build-*/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9f65d5f..c064649 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -202,7 +202,6 @@ endif()
function(amber_default_compile_options TARGET)
if (${COMPILER_IS_LIKE_GNU})
target_compile_options(${TARGET} PRIVATE
- -std=c++11
-fno-exceptions
-fvisibility=hidden
-Wall
@@ -230,7 +229,6 @@ function(amber_default_compile_options TARGET)
endif()
if (MSVC)
- # Specify /EHs for exception handling.
target_compile_options(${TARGET} PRIVATE
/bigobj
/EHsc
@@ -266,6 +264,6 @@ endfunction()
add_subdirectory(third_party)
add_subdirectory(src)
-if (${AMBER_ENABLE_SAMPLES} AND NOT ANDROID)
+if (${AMBER_ENABLE_SAMPLES})
add_subdirectory(samples)
endif()
diff --git a/DEPS b/DEPS
index ff7507f..1286b6d 100644
--- a/DEPS
+++ b/DEPS
@@ -8,23 +8,25 @@ vars = {
'microsoft_git': 'https://github.com/Microsoft',
'nlohmann_git': 'https://github.com/nlohmann',
'swiftshader_git': 'https://swiftshader.googlesource.com',
+ 'martinus_git': 'https://github.com/martinus',
- 'clspv_llvm_revision': '7e30989dabce9ddbca0cbad7a8f25fb4e756d334',
- 'clspv_revision': 'e0406e7053d1bb46b4bbeb57f0f2bbfca32f5612',
- 'cppdap_revision': '1fd23dda91e01550be1a421de307e6fedb2035a9',
+ 'clspv_llvm_revision': 'b70366c9c430e1eadd59d5a1dfbb9c4d84f83de5',
+ 'clspv_revision': 'f99809bdab1710846633b4ec24f5448263e75da7',
+ 'cppdap_revision': '88e89520148b2f95e17ca9348587a28215ffc921',
'cpplint_revision': '26470f9ccb354ff2f6d098f831271a1833701b28',
- 'dxc_revision': '489c2e4d32417cd6693db5673ab071d82e1f5974',
- 'glslang_revision': '7f6559d2802d0653541060f0909e33d137b9c8ba',
- 'googletest_revision': '0555b0eacbc56df1fd762c6aa87bb84be9e4ce7e',
- 'json_revision': '350ff4f7ced7c4117eae2fb93df02823c8021fcb',
- 'lodepng_revision': '7fdcc96a5e5864eee72911c3ca79b1d9f0d12292',
- 'shaderc_revision': '88f9156d7f6a2a30baed1ace196faa3bc5eccc05',
- 'spirv_headers_revision': '5ab5c96198f30804a6a29961b8905f292a8ae600',
- 'spirv_tools_revision': '1f2fcddd3963b9c29bf360daf7656c5977c2aadd',
- 'swiftshader_revision': '04515da400d5fbc22d852af1369c4d46bd54991e',
- 'vulkan_headers_revision': '11c6670b4a4f766ed4f1e777d1b3c3dc082dfa5f',
- 'vulkan_loader_revision': 'be6ccb9ecaf77dfef59246a1e8502e99c8e1a511',
- 'vulkan_validationlayers_revision': '0cb8cc8cfcb2b86a767c9516ac2d62edb4e38ebe',
+ 'dxc_revision': 'c45db48d565a9edc14b025e43b90e62264d06eea',
+ 'glslang_revision': '81cc10a498b25a90147cccd6e8939493c1e9e20e',
+ 'googletest_revision': '16f637fbf4ffc3f7a01fa4eceb7906634565242f',
+ 'json_revision': '4f8fba14066156b73f1189a2b8bd568bde5284c5',
+ 'lodepng_revision': '5601b8272a6850b7c5d693dd0c0e16da50be8d8d',
+ 'shaderc_revision': 'e72186b66bb90ed06aaf15cbdc9a053581a0616b',
+ 'spirv_headers_revision': 'b42ba6d92faf6b4938e6f22ddd186dbdacc98d78',
+ 'spirv_tools_revision': 'a73e724359a274d7cf4f4248eba5be1e7764fbfd',
+ 'swiftshader_revision': 'bca23447ad4667a7b79973569ab5d8d905d211ac',
+ 'vulkan_headers_revision': '1dace16d8044758d32736eb59802d171970e9448',
+ 'vulkan_loader_revision': '8aad559a09388ceb5b968af64a2b965d3886e5a0',
+ 'vulkan_validationlayers_revision': 'a6c1ddca49331d8addde052554487180ee8aec13',
+ 'robin_hood_hashing_revision': '24b3f50f9532153edc23b29ae277dcccfd75a462',
}
deps = {
@@ -75,4 +77,7 @@ deps = {
'third_party/vulkan-loader': Var('khronos_git') + '/Vulkan-Loader.git@' +
Var('vulkan_loader_revision'),
+
+ 'third_party/robin-hood-hashing': Var('martinus_git') + '/robin-hood-hashing.git@' +
+ Var('robin_hood_hashing_revision'),
}
diff --git a/android_gradle/app/build.gradle b/android_gradle/app/build.gradle
index 40c4c54..b756f6b 100644
--- a/android_gradle/app/build.gradle
+++ b/android_gradle/app/build.gradle
@@ -1,26 +1,37 @@
-apply plugin: 'com.android.application'
+plugins {
+ id 'com.android.application'
+}
android {
- compileSdkVersion 29
- buildToolsVersion "29.0.2"
+ compileSdk 30
+ buildToolsVersion "30.0.2"
+ ndkVersion "21.4.7075529"
defaultConfig {
applicationId "com.google.amber"
minSdkVersion 24
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ externalNativeBuild {
+ cmake {
+ arguments "-DAMBER_USE_LOCAL_VULKAN=1"
+ targets "amber_ndk"
+ }
+ }
}
- sourceSets {
- androidTest.manifest.srcFile "src/androidTest/AndroidManifest.xml"
+ externalNativeBuild {
+ cmake {
+ path "../../CMakeLists.txt"
+ }
}
- dependencies {
- androidTestImplementation 'androidx.test:runner:1.1.0'
- androidTestImplementation 'androidx.test:rules:1.1.0'
+ sourceSets {
+ androidTest.manifest.srcFile "src/androidTest/AndroidManifest.xml"
}
buildTypes {
@@ -29,6 +40,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
}
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
sourceSets {
main {
@@ -41,9 +56,10 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation 'androidx.appcompat:appcompat:1.1.0'
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'androidx.test.ext:junit:1.1.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+ implementation 'androidx.appcompat:appcompat:1.3.1'
+ implementation 'com.google.android.material:material:1.4.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
diff --git a/android_gradle/app/src/androidTest/java/com/google/amber/AmberLauncher.java b/android_gradle/app/src/androidTest/java/com/google/amber/AmberLauncher.java
index 4864843..ad92154 100644
--- a/android_gradle/app/src/androidTest/java/com/google/amber/AmberLauncher.java
+++ b/android_gradle/app/src/androidTest/java/com/google/amber/AmberLauncher.java
@@ -54,7 +54,7 @@ public class AmberLauncher {
String stdout_file = args.getString("stdout", new File(outputDir, "amber_stdout.txt").toString());
String stderr_file = args.getString("stderr", new File(outputDir, "amber_stderr.txt").toString());
- int res = Amber.androidMain(args_list.toArray(new String[0]), stdout_file, stderr_file);
+ int res = Amber.androidHelper(args_list.toArray(new String[0]), stdout_file, stderr_file);
// If the process crashes during the above call or we call System.exit below, the output
// from `adb shell am instrument ...` will be:
diff --git a/android_gradle/app/src/main/AndroidManifest.xml b/android_gradle/app/src/main/AndroidManifest.xml
index 0ab9856..c74c390 100644
--- a/android_gradle/app/src/main/AndroidManifest.xml
+++ b/android_gradle/app/src/main/AndroidManifest.xml
@@ -4,6 +4,7 @@
<application
android:allowBackup="true"
+ android:fullBackupOnly="true"
android:label="Amber"
android:supportsRtl="true">
<meta-data
diff --git a/android_gradle/app/src/main/java/com/google/amber/Amber.java b/android_gradle/app/src/main/java/com/google/amber/Amber.java
index 8319ccf..008c528 100644
--- a/android_gradle/app/src/main/java/com/google/amber/Amber.java
+++ b/android_gradle/app/src/main/java/com/google/amber/Amber.java
@@ -19,5 +19,5 @@ public class Amber {
System.loadLibrary("amber_ndk");
}
- public static native int androidMain(String[] args, String stdout_file, String stderr_file);
+ public static native int androidHelper(String[] args, String stdout_file, String stderr_file);
}
diff --git a/android_gradle/build.gradle b/android_gradle/build.gradle
index 82c93bf..d340082 100644
--- a/android_gradle/build.gradle
+++ b/android_gradle/build.gradle
@@ -4,25 +4,16 @@ buildscript {
repositories {
google()
- jcenter()
- maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.0.0-alpha04'
+ classpath 'com.android.tools.build:gradle:7.0.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
-allprojects {
- repositories {
- google()
- jcenter()
- maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
- }
-}
-
task clean(type: Delete) {
delete rootProject.buildDir
}
diff --git a/android_gradle/gradle.properties b/android_gradle/gradle.properties
index 199d16e..4941ecd 100644
--- a/android_gradle/gradle.properties
+++ b/android_gradle/gradle.properties
@@ -6,7 +6,7 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx1536m
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
diff --git a/android_gradle/gradle/wrapper/gradle-wrapper.jar b/android_gradle/gradle/wrapper/gradle-wrapper.jar
index f6b961f..e708b1c 100644
--- a/android_gradle/gradle/wrapper/gradle-wrapper.jar
+++ b/android_gradle/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/android_gradle/gradle/wrapper/gradle-wrapper.properties b/android_gradle/gradle/wrapper/gradle-wrapper.properties
index 421d5b6..e81b594 100644
--- a/android_gradle/gradle/wrapper/gradle-wrapper.properties
+++ b/android_gradle/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Dec 09 14:37:37 GMT 2019
+#Sat Sep 25 16:43:12 BST 2021
distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-rc-1-all.zip
+zipStoreBase=GRADLE_USER_HOME
diff --git a/android_gradle/settings.gradle b/android_gradle/settings.gradle
index 9a979bb..2c4357f 100644
--- a/android_gradle/settings.gradle
+++ b/android_gradle/settings.gradle
@@ -1,2 +1,9 @@
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
rootProject.name='Amber'
include ':app'
diff --git a/docs/amber_script.md b/docs/amber_script.md
index 295cdc7..7c78d82 100644
--- a/docs/amber_script.md
+++ b/docs/amber_script.md
@@ -48,6 +48,20 @@ with:
* `Storage16BitFeatures.storageInputOutput16`
* `SubgroupSizeControl.subgroupSizeControl`
* `SubgroupSizeControl.computeFullSubgroups`
+ * `SubgroupSupportedOperations.basic`
+ * `SubgroupSupportedOperations.vote`
+ * `SubgroupSupportedOperations.arithmetic`
+ * `SubgroupSupportedOperations.ballot`
+ * `SubgroupSupportedOperations.shuffle`
+ * `SubgroupSupportedOperations.shuffleRelative`
+ * `SubgroupSupportedOperations.clustered`
+ * `SubgroupSupportedOperations.quad`
+ * `SubgroupSupportedStages.vertex`
+ * `SubgroupSupportedStages.tessellationControl`
+ * `SubgroupSupportedStages.tessellationEvaluation`
+ * `SubgroupSupportedStages.geometry`
+ * `SubgroupSupportedStages.fragment`
+ * `SubgroupSupportedStages.compute`
Extensions can be enabled with the `DEVICE_EXTENSION` and `INSTANCE_EXTENSION`
@@ -427,6 +441,11 @@ The following commands are all specified within the `PIPELINE` command.
POLYGON_MODE {mode}
```
+```groovy
+ # Set the number of patch control points used by tessellation. The default value is 3.
+ PATCH_CONTROL_POINTS {control_points}
+```
+
#### Compare operations
* `never`
* `less`
@@ -478,6 +497,96 @@ The following commands are all specified within the `PIPELINE` command.
END
```
+#### Blend factors
+* `zero`
+* `one`
+* `src_color`
+* `one_minus_src_color`
+* `dst_color`
+* `one_minus_dst_color`
+* `src_alpha`
+* `one_minus_src_alpha`
+* `dst_alpha`
+* `one_minus_dst_alpha`
+* `constant_color`
+* `one_minus_constant_color`
+* `constant_alpha`
+* `one_minus_constant_alpha`
+* `src_alpha_saturate`
+* `src1_color`
+* `one_minus_src1_color`
+* `src1_alpha`
+* `one_minus_src1_alpha`
+
+#### Blend operations
+* `add`
+* `substract`
+* `reverse_substract`
+* `min`
+* `max`
+
+The following operations also require VK_EXT_blend_operation_advanced
+when using a Vulkan backend.
+* `zero`
+* `src`
+* `dst`
+* `src_over`
+* `dst_over`
+* `src_in`
+* `dst_in`
+* `src_out`
+* `dst_out`
+* `src_atop`
+* `dst_atop`
+* `xor`
+* `multiply`
+* `screen`
+* `overlay`
+* `darken`
+* `lighten`
+* `color_dodge`
+* `color_burn`
+* `hard_light`
+* `soft_light`
+* `difference`
+* `exclusion`
+* `invert`
+* `invert_rgb`
+* `linear_dodge`
+* `linear_burn`
+* `vivid_light`
+* `linear_light`
+* `pin_light`
+* `hard_mix`
+* `hsl_hue`
+* `hsl_saturation`
+* `hsl_color`
+* `hsl_luminosity`
+* `plus`
+* `plus_clamped`
+* `plus_clamped_alpha`
+* `plus_darker`
+* `minus`
+* `minus_clamped`
+* `contrast`
+* `invert_org`
+* `red`
+* `green`
+* `blue`
+
+```groovy
+ # Enable alpha blending and set blend factors and operations. Available
+ # blend factors and operations are listed above.
+ BLEND
+ SRC_COLOR_FACTOR {src_color_factor}
+ DST_COLOR_FACTOR {dst_color_factor}
+ COLOR_OP {color_op}
+ SRC_ALPHA_FACTOR {src_alpha_factor}
+ DST_ALPHA_FACTOR {dst_alpha_factor}
+ ALPHA_OP {alpha_op}
+ END
+```
+
```groovy
# Set the size of the render buffers. |width| and |height| are integers and
# default to 250x250.
@@ -536,6 +645,11 @@ contain image attachment content, depth/stencil content, uniform buffers, etc.
# pipelines.
BIND BUFFER {buffer_name} AS depth_stencil
+ # Attach |buffer_name| as a multisample resolve target. The order of resolve
+ # target images match with the order of color attachments that have more than
+ # one sample.
+ BIND BUFFER {buffer_name} AS resolve
+
# Attach |buffer_name| as the push_constant buffer. There can be only one
# push constant buffer attached to a pipeline.
BIND BUFFER {buffer_name} AS push_constant
diff --git a/docs/debugger.md b/docs/debugger.md
index 6c3208b..dc887d0 100644
--- a/docs/debugger.md
+++ b/docs/debugger.md
@@ -3,9 +3,7 @@
This document describes Amber's shader debugger testing framework, which allows developers to write tests for Vulkan drivers that expose shader debugging functionality via the [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/).
---
-**Work In Progress**
-
-Note that shader debugging is very much work-in-progress:
+**Caveats**
* Vulkan shader debugging currently does not have a formalized specification. A shader debugger implementation is being developed in [SwiftShader](https://swiftshader.googlesource.com/SwiftShader/), which one day may become a reference implementation for a formal specifiction.
* Currently SwiftShader is the only Vulkan driver to implement a [DAP based shader debugger](https://swiftshader.googlesource.com/SwiftShader/+/refs/heads/master/docs/VulkanShaderDebugging.md). This implementation is also work-in-progress, and may significantly change.
@@ -189,4 +187,4 @@ The `amber::Engine::Debugger` interface can be obtained from the `amber::Engine`
* If the `amber::Command` holds a `amber::debug::Script`, then this script is executed on the `amber::Engine::Debugger` using the `amber::debug::Script::Run(amber::debug::Events *)` method, before the Vulkan command is executed.
* The command is then executed with `amber::Executor::ExecuteCommand()`
* Once the command has completed, all debugger threads are synchronized and debugger test results are collected with a call to `amber::Engine::Debugger::Flush()`.
-* This process is repeated for all commands in the script. \ No newline at end of file
+* This process is repeated for all commands in the script.
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index 3fa1882..1e91c4d 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -74,3 +74,11 @@ target_include_directories(image_diff PRIVATE "${CMAKE_BINARY_DIR}")
target_link_libraries(image_diff libamber "lodepng")
amber_default_compile_options(image_diff)
set_target_properties(image_diff PROPERTIES OUTPUT_NAME "image_diff")
+
+if (ANDROID)
+ add_library(amber_ndk SHARED android_helper.cc ${AMBER_SOURCES})
+ target_include_directories(amber_ndk PRIVATE "${CMAKE_BINARY_DIR}")
+ target_link_libraries(amber_ndk libamber ${AMBER_EXTRA_LIBS})
+ amber_default_compile_options(amber_ndk)
+ target_compile_definitions(amber_ndk PRIVATE AMBER_ANDROID_MAIN=1)
+endif()
diff --git a/samples/amber.cc b/samples/amber.cc
index d037ba4..5973dba 100644
--- a/samples/amber.cc
+++ b/samples/amber.cc
@@ -447,7 +447,15 @@ std::string disassemble(const std::string& env,
} // namespace
+#ifdef AMBER_ANDROID_MAIN
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
+int android_main(int argc, const char** argv) {
+#pragma clang diagnostic pop
+#else
int main(int argc, const char** argv) {
+#endif
std::vector<std::string> args(argv, argv + argc);
Options options;
SampleDelegate delegate;
diff --git a/samples/android_main.cc b/samples/android_helper.cc
index b24a9bb..7da69ad 100644
--- a/samples/android_main.cc
+++ b/samples/android_helper.cc
@@ -18,16 +18,20 @@
#include <string>
#include <vector>
-extern int main(int argc, const char** argv);
+extern int android_main(int argc, const char** argv);
-extern "C" JNIEXPORT JNICALL int Java_com_google_amber_Amber_androidMain(
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
+
+extern "C" JNIEXPORT JNICALL int Java_com_google_amber_Amber_androidHelper(
JNIEnv* env,
jobject,
jobjectArray args,
jstring stdoutFile,
jstring stderrFile) {
- const char* stdout_file_cstr = env->GetStringUTFChars(stdoutFile, NULL);
- const char* stderr_file_cstr = env->GetStringUTFChars(stderrFile, NULL);
+ const char* stdout_file_cstr = env->GetStringUTFChars(stdoutFile, nullptr);
+ const char* stderr_file_cstr = env->GetStringUTFChars(stderrFile, nullptr);
// Redirect std output to a file
freopen(stdout_file_cstr, "w", stdout);
@@ -43,7 +47,7 @@ extern "C" JNIEXPORT JNICALL int Java_com_google_amber_Amber_androidMain(
for (jsize i = 0; i < arg_count; i++) {
jstring js = static_cast<jstring>(env->GetObjectArrayElement(args, i));
- const char* arg_cstr = env->GetStringUTFChars(js, NULL);
+ const char* arg_cstr = env->GetStringUTFChars(js, nullptr);
argv_string.push_back(arg_cstr);
env->ReleaseStringUTFChars(js, arg_cstr);
}
@@ -53,5 +57,7 @@ extern "C" JNIEXPORT JNICALL int Java_com_google_amber_Amber_androidMain(
for (const std::string& arg : argv_string)
argv.push_back(arg.c_str());
- return main(argv.size(), argv.data());
+ return android_main(static_cast<int>(argv.size()), argv.data());
}
+
+#pragma clang diagnostic pop
diff --git a/samples/config_helper_vulkan.cc b/samples/config_helper_vulkan.cc
index 68114ab..6a82a4a 100644
--- a/samples/config_helper_vulkan.cc
+++ b/samples/config_helper_vulkan.cc
@@ -758,25 +758,60 @@ amber::Result ConfigHelperVulkan::CheckVulkanPhysicalDeviceRequirements(
const VkPhysicalDevice physical_device,
const std::vector<std::string>& required_features,
const std::vector<std::string>& required_extensions) {
+ available_device_extensions_ = GetAvailableDeviceExtensions(physical_device);
+ if (!AreAllExtensionsSupported(available_device_extensions_,
+ required_extensions)) {
+ return amber::Result("Device does not support all required extensions");
+ }
+ for (const auto& ext : available_device_extensions_) {
+ if (ext == "VK_KHR_shader_float16_int8")
+ supports_shader_float16_int8_ = true;
+ else if (ext == "VK_KHR_8bit_storage")
+ supports_shader_8bit_storage_ = true;
+ else if (ext == "VK_KHR_16bit_storage")
+ supports_shader_16bit_storage_ = true;
+ else if (ext == "VK_EXT_subgroup_size_control")
+ supports_subgroup_size_control_ = true;
+ }
+
VkPhysicalDeviceFeatures required_vulkan_features =
VkPhysicalDeviceFeatures();
if (supports_get_physical_device_properties2_) {
- VkPhysicalDeviceSubgroupSizeControlFeaturesEXT size_control =
- VkPhysicalDeviceSubgroupSizeControlFeaturesEXT();
- size_control.sType =
+ VkPhysicalDeviceSubgroupSizeControlFeaturesEXT
+ subgroup_size_control_features = {};
+ VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointers_features = {};
+ VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8_features = {};
+ VkPhysicalDevice8BitStorageFeaturesKHR storage_8bit_features = {};
+ VkPhysicalDevice16BitStorageFeaturesKHR storage_16bit_features = {};
+
+ subgroup_size_control_features.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT;
- size_control.pNext = nullptr;
+ subgroup_size_control_features.pNext = nullptr;
- VkPhysicalDeviceVariablePointerFeaturesKHR var_ptrs =
- VkPhysicalDeviceVariablePointerFeaturesKHR();
- var_ptrs.sType =
+ // Add subgroup size control struct into the chain only if
+ // VK_EXT_subgroup_size_control is supported.
+ variable_pointers_features.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR;
- var_ptrs.pNext = &size_control;
+ variable_pointers_features.pNext = supports_subgroup_size_control_
+ ? &subgroup_size_control_features
+ : nullptr;
+
+ float16_int8_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
+ float16_int8_features.pNext = &variable_pointers_features;
+
+ storage_8bit_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR;
+ storage_8bit_features.pNext = &float16_int8_features;
+
+ storage_16bit_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;
+ storage_16bit_features.pNext = &storage_8bit_features;
VkPhysicalDeviceFeatures2KHR features2 = VkPhysicalDeviceFeatures2KHR();
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
- features2.pNext = &var_ptrs;
+ features2.pNext = &storage_16bit_features;
auto vkGetPhysicalDeviceFeatures2KHR =
reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(
@@ -794,13 +829,34 @@ amber::Result ConfigHelperVulkan::CheckVulkanPhysicalDeviceRequirements(
}
if ((feature == kVariablePointers &&
- var_ptrs.variablePointers == VK_FALSE) ||
+ variable_pointers_features.variablePointers == VK_FALSE) ||
(feature == kVariablePointersStorageBuffer &&
- var_ptrs.variablePointersStorageBuffer == VK_FALSE) ||
+ variable_pointers_features.variablePointersStorageBuffer ==
+ VK_FALSE) ||
(feature == kSubgroupSizeControl &&
- size_control.subgroupSizeControl == VK_FALSE) ||
+ subgroup_size_control_features.subgroupSizeControl == VK_FALSE) ||
(feature == kComputeFullSubgroups &&
- size_control.computeFullSubgroups == VK_FALSE)) {
+ subgroup_size_control_features.computeFullSubgroups == VK_FALSE) ||
+ (feature == kFloat16Int8_Float16 &&
+ float16_int8_features.shaderFloat16 == VK_FALSE) ||
+ (feature == kFloat16Int8_Int8 &&
+ float16_int8_features.shaderInt8 == VK_FALSE) ||
+ (feature == k8BitStorage_Storage &&
+ storage_8bit_features.storageBuffer8BitAccess == VK_FALSE) ||
+ (feature == k8BitStorage_UniformAndStorage &&
+ storage_8bit_features.uniformAndStorageBuffer8BitAccess ==
+ VK_FALSE) ||
+ (feature == k8BitStorage_PushConstant &&
+ storage_8bit_features.storagePushConstant8 == VK_FALSE) ||
+ (feature == k16BitStorage_Storage &&
+ storage_16bit_features.storageBuffer16BitAccess == VK_FALSE) ||
+ (feature == k16BitStorage_InputOutput &&
+ storage_16bit_features.storageInputOutput16 == VK_FALSE) ||
+ (feature == k16BitStorage_PushConstant &&
+ storage_16bit_features.storagePushConstant16 == VK_FALSE) ||
+ (feature == k16BitStorage_UniformAndStorage &&
+ storage_16bit_features.uniformAndStorageBuffer16BitAccess ==
+ VK_FALSE)) {
return amber::Result("Device does not support all required features");
}
}
@@ -823,22 +879,6 @@ amber::Result ConfigHelperVulkan::CheckVulkanPhysicalDeviceRequirements(
return amber::Result("Device does not support all required features");
}
- available_device_extensions_ = GetAvailableDeviceExtensions(physical_device);
- if (!AreAllExtensionsSupported(available_device_extensions_,
- required_extensions)) {
- return amber::Result("Device does not support all required extensions");
- }
- for (const auto& ext : available_device_extensions_) {
- if (ext == "VK_KHR_shader_float16_int8")
- supports_shader_float16_int8_ = true;
- else if (ext == "VK_KHR_8bit_storage")
- supports_shader_8bit_storage_ = true;
- else if (ext == "VK_KHR_16bit_storage")
- supports_shader_16bit_storage_ = true;
- else if (ext == "VK_EXT_subgroup_size_control")
- supports_subgroup_size_control_ = true;
- }
-
vulkan_queue_family_index_ = ChooseQueueFamilyIndex(physical_device);
if (vulkan_queue_family_index_ == std::numeric_limits<uint32_t>::max()) {
return amber::Result("Device does not support required queue flags");
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 901681f..e51d1b0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -124,6 +124,10 @@ endif()
if (${Vulkan_FOUND})
target_link_libraries(libamber libamberenginevulkan)
target_include_directories(libamber PRIVATE "${VulkanHeaders_INCLUDE_DIR}")
+
+ if (${VULKAN_CTS_HEADER} AND DEFINED AMBER_CTS_INL_DIR)
+ target_include_directories(libamber PRIVATE "${AMBER_CTS_INL_DIR}")
+ endif()
endif()
if (${Dawn_FOUND})
target_link_libraries(libamber libamberenginedawn)
@@ -156,6 +160,7 @@ if (${AMBER_ENABLE_TESTS})
amberscript/parser_shader_opt_test.cc
amberscript/parser_shader_test.cc
amberscript/parser_stencil_test.cc
+ amberscript/parser_blend_test.cc
amberscript/parser_struct_test.cc
amberscript/parser_subgroup_size_control_test.cc
amberscript/parser_test.cc
diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc
index 809baa1..d3e0eb6 100644
--- a/src/amberscript/parser.cc
+++ b/src/amberscript/parser.cc
@@ -622,6 +622,10 @@ Result Parser::ParsePipelineBody(const std::string& cmd_name,
r = ParsePipelineStencil(pipeline.get());
} else if (tok == "SUBGROUP") {
r = ParsePipelineSubgroup(pipeline.get());
+ } else if (tok == "PATCH_CONTROL_POINTS") {
+ r = ParsePipelinePatchControlPoints(pipeline.get());
+ } else if (tok == "BLEND") {
+ r = ParsePipelineBlend(pipeline.get());
} else {
r = Result("unknown token in pipeline block: " + tok);
}
@@ -931,6 +935,20 @@ Result Parser::ParsePipelineSubgroup(Pipeline* pipeline) {
return ValidateEndOfStatement("SUBGROUP command");
}
+Result Parser::ParsePipelinePatchControlPoints(Pipeline* pipeline) {
+ auto token = tokenizer_->NextToken();
+ if (token->IsEOL() || token->IsEOS())
+ return Result(
+ "missing number of control points in PATCH_CONTROL_POINTS command");
+
+ if (!token->IsInteger())
+ return Result("expecting integer for the number of control points");
+
+ pipeline->GetPipelineData()->SetPatchControlPoints(token->AsUint32());
+
+ return ValidateEndOfStatement("PATCH_CONTROL_POINTS command");
+}
+
Result Parser::ParsePipelineFramebufferSize(Pipeline* pipeline) {
auto token = tokenizer_->NextToken();
if (token->IsEOL() || token->IsEOS())
@@ -1046,6 +1064,8 @@ Result Parser::ToBufferType(const std::string& name, BufferType* type) {
*type = BufferType::kUniformTexelBuffer;
else if (name == "storage_texel_buffer")
*type = BufferType::kStorageTexelBuffer;
+ else if (name == "resolve")
+ *type = BufferType::kResolve;
else
return Result("unknown buffer_type: " + name);
@@ -1160,6 +1180,8 @@ Result Parser::ParsePipelineBind(Pipeline* pipeline) {
for (auto& buf : buffers)
buf->SetSampler(sampler);
+ } else if (buffer_type == BufferType::kResolve) {
+ r = pipeline->AddResolveTarget(buffer);
}
}
@@ -1843,6 +1865,98 @@ Result Parser::ParsePipelineStencil(Pipeline* pipeline) {
return ValidateEndOfStatement("STENCIL command");
}
+Result Parser::ParsePipelineBlend(Pipeline* pipeline) {
+ pipeline->GetPipelineData()->SetEnableBlend(true);
+
+ while (true) {
+ auto token = tokenizer_->NextToken();
+ if (token->IsEOL())
+ continue;
+ if (token->IsEOS())
+ return Result("BLEND missing END command");
+ if (!token->IsIdentifier())
+ return Result("BLEND options must be identifiers");
+ if (token->AsString() == "END")
+ break;
+
+ if (token->AsString() == "SRC_COLOR_FACTOR") {
+ token = tokenizer_->NextToken();
+
+ if (!token->IsIdentifier())
+ return Result("BLEND invalid value for SRC_COLOR_FACTOR");
+
+ const auto factor = NameToBlendFactor(token->AsString());
+ if (factor == BlendFactor::kUnknown)
+ return Result("BLEND invalid value for SRC_COLOR_FACTOR: " +
+ token->AsString());
+ pipeline->GetPipelineData()->SetSrcColorBlendFactor(
+ NameToBlendFactor(token->AsString()));
+ } else if (token->AsString() == "DST_COLOR_FACTOR") {
+ token = tokenizer_->NextToken();
+
+ if (!token->IsIdentifier())
+ return Result("BLEND invalid value for DST_COLOR_FACTOR");
+
+ const auto factor = NameToBlendFactor(token->AsString());
+ if (factor == BlendFactor::kUnknown)
+ return Result("BLEND invalid value for DST_COLOR_FACTOR: " +
+ token->AsString());
+ pipeline->GetPipelineData()->SetDstColorBlendFactor(
+ NameToBlendFactor(token->AsString()));
+ } else if (token->AsString() == "SRC_ALPHA_FACTOR") {
+ token = tokenizer_->NextToken();
+
+ if (!token->IsIdentifier())
+ return Result("BLEND invalid value for SRC_ALPHA_FACTOR");
+
+ const auto factor = NameToBlendFactor(token->AsString());
+ if (factor == BlendFactor::kUnknown)
+ return Result("BLEND invalid value for SRC_ALPHA_FACTOR: " +
+ token->AsString());
+ pipeline->GetPipelineData()->SetSrcAlphaBlendFactor(
+ NameToBlendFactor(token->AsString()));
+ } else if (token->AsString() == "DST_ALPHA_FACTOR") {
+ token = tokenizer_->NextToken();
+
+ if (!token->IsIdentifier())
+ return Result("BLEND invalid value for DST_ALPHA_FACTOR");
+
+ const auto factor = NameToBlendFactor(token->AsString());
+ if (factor == BlendFactor::kUnknown)
+ return Result("BLEND invalid value for DST_ALPHA_FACTOR: " +
+ token->AsString());
+ pipeline->GetPipelineData()->SetDstAlphaBlendFactor(
+ NameToBlendFactor(token->AsString()));
+ } else if (token->AsString() == "COLOR_OP") {
+ token = tokenizer_->NextToken();
+
+ if (!token->IsIdentifier())
+ return Result("BLEND invalid value for COLOR_OP");
+
+ const auto op = NameToBlendOp(token->AsString());
+ if (op == BlendOp::kUnknown)
+ return Result("BLEND invalid value for COLOR_OP: " + token->AsString());
+ pipeline->GetPipelineData()->SetColorBlendOp(
+ NameToBlendOp(token->AsString()));
+ } else if (token->AsString() == "ALPHA_OP") {
+ token = tokenizer_->NextToken();
+
+ if (!token->IsIdentifier())
+ return Result("BLEND invalid value for ALPHA_OP");
+
+ const auto op = NameToBlendOp(token->AsString());
+ if (op == BlendOp::kUnknown)
+ return Result("BLEND invalid value for ALPHA_OP: " + token->AsString());
+ pipeline->GetPipelineData()->SetAlphaBlendOp(
+ NameToBlendOp(token->AsString()));
+ } else {
+ return Result("BLEND invalid value for BLEND: " + token->AsString());
+ }
+ }
+
+ return ValidateEndOfStatement("BLEND command");
+}
+
Result Parser::ParseStruct() {
auto token = tokenizer_->NextToken();
if (!token->IsIdentifier())
diff --git a/src/amberscript/parser.h b/src/amberscript/parser.h
index 6fb25ce..25d3493 100644
--- a/src/amberscript/parser.h
+++ b/src/amberscript/parser.h
@@ -64,6 +64,7 @@ class Parser : public amber::Parser {
Result ParsePipelineShaderOptimizations(Pipeline*);
Result ParsePipelineShaderCompileOptions(Pipeline*);
Result ParsePipelineSubgroup(Pipeline* pipeline);
+ Result ParsePipelinePatchControlPoints(Pipeline* pipeline);
Result ParsePipelineFramebufferSize(Pipeline*);
Result ParsePipelineViewport(Pipeline*);
Result ParsePipelineBind(Pipeline*);
@@ -73,6 +74,7 @@ class Parser : public amber::Parser {
Result ParsePipelinePolygonMode(Pipeline*);
Result ParsePipelineDepth(Pipeline* pipeline);
Result ParsePipelineStencil(Pipeline* pipeline);
+ Result ParsePipelineBlend(Pipeline* pipeline);
Result ParseRun();
Result ParseDebug();
Result ParseDebugThread(debug::Events*, Pipeline* pipeline);
diff --git a/src/amberscript/parser_bind_test.cc b/src/amberscript/parser_bind_test.cc
index a39b69e..8aac5e5 100644
--- a/src/amberscript/parser_bind_test.cc
+++ b/src/amberscript/parser_bind_test.cc
@@ -3508,5 +3508,132 @@ END
r.Error());
}
+TEST_F(AmberScriptParserTest, BindResolveTarget) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+IMAGE my_fb_ms DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
+IMAGE my_fb DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+
+ FRAMEBUFFER_SIZE 64 64
+ BIND BUFFER my_fb_ms AS color LOCATION 0
+ BIND BUFFER my_fb AS resolve
+END)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ auto script = parser.GetScript();
+ const auto& pipelines = script->GetPipelines();
+ ASSERT_EQ(1U, pipelines.size());
+
+ const auto* pipeline = pipelines[0].get();
+ const auto& resolve_targets = pipeline->GetResolveTargets();
+ ASSERT_EQ(1U, resolve_targets.size());
+
+ const auto& buf_info = resolve_targets[0];
+ ASSERT_TRUE(buf_info.buffer != nullptr);
+ EXPECT_EQ(64u * 64u, buf_info.buffer->ElementCount());
+ EXPECT_EQ(64u * 64u * 4u, buf_info.buffer->ValueCount());
+ EXPECT_EQ(64u * 64u * 4u * sizeof(float), buf_info.buffer->GetSizeInBytes());
+}
+
+TEST_F(AmberScriptParserTest, BindResolveTargetMissingBuffer) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+
+ BIND BUFFER AS resolve
+END)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ EXPECT_EQ("12: unknown buffer: AS", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, BindResolveTargetNonDeclaredBuffer) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+IMAGE my_fb_ms DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
+
+PIPELINE graphics my_pipeline
+ATTACH my_shader
+ATTACH my_fragment
+
+FRAMEBUFFER_SIZE 64 64
+BIND BUFFER my_fb_ms AS color LOCATION 0
+BIND BUFFER my_fb AS resolve
+END)";
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ EXPECT_EQ("14: unknown buffer: my_fb", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, BindMultipleResolveTargets) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+IMAGE my_fb_ms0 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
+IMAGE my_fb_ms1 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
+IMAGE my_fb_ms2 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
+IMAGE my_fb0 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
+IMAGE my_fb1 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
+IMAGE my_fb2 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+
+ FRAMEBUFFER_SIZE 64 64
+ BIND BUFFER my_fb_ms0 AS color LOCATION 0
+ BIND BUFFER my_fb_ms1 AS color LOCATION 1
+ BIND BUFFER my_fb_ms2 AS color LOCATION 2
+ BIND BUFFER my_fb0 AS resolve
+ BIND BUFFER my_fb1 AS resolve
+ BIND BUFFER my_fb2 AS resolve
+END)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ auto script = parser.GetScript();
+ const auto& pipelines = script->GetPipelines();
+ ASSERT_EQ(1U, pipelines.size());
+
+ const auto* pipeline = pipelines[0].get();
+ const auto& resolve_targets = pipeline->GetResolveTargets();
+ ASSERT_EQ(3U, resolve_targets.size());
+
+ for (const auto& buf_info : resolve_targets) {
+ ASSERT_TRUE(buf_info.buffer != nullptr);
+ EXPECT_EQ(64u * 64u, buf_info.buffer->ElementCount());
+ EXPECT_EQ(64u * 64u * 4u, buf_info.buffer->ValueCount());
+ EXPECT_EQ(64u * 64u * 4u * sizeof(float),
+ buf_info.buffer->GetSizeInBytes());
+ }
+}
+
} // namespace amberscript
} // namespace amber
diff --git a/src/amberscript/parser_blend_test.cc b/src/amberscript/parser_blend_test.cc
new file mode 100644
index 0000000..013ccbd
--- /dev/null
+++ b/src/amberscript/parser_blend_test.cc
@@ -0,0 +1,140 @@
+// Copyright 2021 The Amber 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
+//
+// 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 parseried.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gtest/gtest.h"
+#include "src/amberscript/parser.h"
+
+namespace amber {
+namespace amberscript {
+
+using AmberScriptParserTest = testing::Test;
+
+TEST_F(AmberScriptParserTest, BlendAllValues) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+ BIND BUFFER my_fb AS color LOCATION 0
+
+ BLEND
+ SRC_COLOR_FACTOR src_alpha
+ DST_COLOR_FACTOR one_minus_src_alpha
+ COLOR_OP add
+ SRC_ALPHA_FACTOR one
+ DST_ALPHA_FACTOR zero
+ ALPHA_OP max
+ END
+END)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ auto script = parser.GetScript();
+ const auto& pipelines = script->GetPipelines();
+ ASSERT_EQ(1U, pipelines.size());
+
+ auto* pipeline = pipelines[0].get();
+
+ ASSERT_TRUE(pipeline->GetPipelineData()->GetEnableBlend());
+ ASSERT_EQ(BlendFactor::kSrcAlpha,
+ pipeline->GetPipelineData()->GetSrcColorBlendFactor());
+ ASSERT_EQ(BlendFactor::kOneMinusSrcAlpha,
+ pipeline->GetPipelineData()->GetDstColorBlendFactor());
+ ASSERT_EQ(BlendOp::kAdd,
+ pipeline->GetPipelineData()->GetColorBlendOp());
+
+ ASSERT_EQ(BlendFactor::kOne,
+ pipeline->GetPipelineData()->GetSrcAlphaBlendFactor());
+ ASSERT_EQ(BlendFactor::kZero,
+ pipeline->GetPipelineData()->GetDstAlphaBlendFactor());
+ ASSERT_EQ(BlendOp::kMax,
+ pipeline->GetPipelineData()->GetAlphaBlendOp());
+}
+
+TEST_F(AmberScriptParserTest, BlendDefaultValues) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+ BIND BUFFER my_fb AS color LOCATION 0
+
+ BLEND
+ END
+END)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ auto script = parser.GetScript();
+ const auto& pipelines = script->GetPipelines();
+ ASSERT_EQ(1U, pipelines.size());
+
+ auto* pipeline = pipelines[0].get();
+
+ ASSERT_TRUE(pipeline->GetPipelineData()->GetEnableBlend());
+ ASSERT_EQ(BlendFactor::kOne,
+ pipeline->GetPipelineData()->GetSrcColorBlendFactor());
+ ASSERT_EQ(BlendFactor::kZero,
+ pipeline->GetPipelineData()->GetDstColorBlendFactor());
+ ASSERT_EQ(BlendOp::kAdd,
+ pipeline->GetPipelineData()->GetColorBlendOp());
+
+ ASSERT_EQ(BlendFactor::kOne,
+ pipeline->GetPipelineData()->GetSrcAlphaBlendFactor());
+ ASSERT_EQ(BlendFactor::kZero,
+ pipeline->GetPipelineData()->GetDstAlphaBlendFactor());
+ ASSERT_EQ(BlendOp::kAdd,
+ pipeline->GetPipelineData()->GetAlphaBlendOp());
+}
+
+TEST_F(AmberScriptParserTest, BlendInvalidColorFactor) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+ BIND BUFFER my_fb AS color LOCATION 0
+
+ BLEND
+ SRC_COLOR_FACTOR foo
+ END
+END)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess()) << r.Error();
+ EXPECT_EQ("14: BLEND invalid value for SRC_COLOR_FACTOR: foo", r.Error());
+}
+
+} // namespace amberscript
+} // namespace amber
diff --git a/src/amberscript/parser_pipeline_test.cc b/src/amberscript/parser_pipeline_test.cc
index 2b56e2e..4707dd9 100644
--- a/src/amberscript/parser_pipeline_test.cc
+++ b/src/amberscript/parser_pipeline_test.cc
@@ -61,6 +61,8 @@ END
EXPECT_EQ(kShaderTypeFragment, shaders[1].GetShader()->GetType());
EXPECT_EQ(static_cast<uint32_t>(0),
shaders[1].GetShaderOptimizations().size());
+
+ EXPECT_EQ(pipelines[0]->GetPipelineData()->GetPatchControlPoints(), 3u);
}
TEST_F(AmberScriptParserTest, PipelineMissingEnd) {
@@ -541,5 +543,85 @@ END
EXPECT_EQ(4u, s2[0].GetSpecialization().at(3));
}
+TEST_F(AmberScriptParserTest, PipelinePatchControlPoints) {
+ std::string in = R"(
+DEVICE_FEATURE tessellationShader
+
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+SHADER tessellation_control my_tesc GLSL
+# GLSL Shader
+END
+
+SHADER tessellation_evaluation my_tese GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_tesc
+ ATTACH my_tese
+ ATTACH my_fragment
+
+ PATCH_CONTROL_POINTS 4
+END
+)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ auto script = parser.GetScript();
+ const auto& pipelines = script->GetPipelines();
+ ASSERT_EQ(1U, pipelines.size());
+
+ EXPECT_EQ(pipelines[0]->GetPipelineData()->GetPatchControlPoints(), 4u);
+}
+
+TEST_F(AmberScriptParserTest, PipelineDerivePatchControlPoints) {
+ std::string in = R"(
+DEVICE_FEATURE tessellationShader
+
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+SHADER tessellation_control my_tesc GLSL
+# GLSL Shader
+END
+
+SHADER tessellation_evaluation my_tese GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_tesc
+ ATTACH my_tese
+ ATTACH my_fragment
+
+ PATCH_CONTROL_POINTS 4
+END
+
+DERIVE_PIPELINE child_pipeline FROM my_pipeline
+END
+)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ auto script = parser.GetScript();
+ const auto& pipelines = script->GetPipelines();
+ ASSERT_EQ(2U, pipelines.size());
+
+ EXPECT_EQ(pipelines[0]->GetPipelineData()->GetPatchControlPoints(), 4u);
+ EXPECT_EQ(pipelines[1]->GetPipelineData()->GetPatchControlPoints(), 4u);
+}
+
} // namespace amberscript
} // namespace amber
diff --git a/src/buffer.h b/src/buffer.h
index 18f7fed..90f3b01 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -62,7 +62,9 @@ enum class BufferType : int8_t {
/// A uniform texel buffer.
kUniformTexelBuffer,
/// A storage texel buffer.
- kStorageTexelBuffer
+ kStorageTexelBuffer,
+ /// A resolve target.
+ kResolve
};
enum class InputRate : int8_t {
diff --git a/src/command_data.cc b/src/command_data.cc
index 80083e1..c0b7612 100644
--- a/src/command_data.cc
+++ b/src/command_data.cc
@@ -54,4 +54,154 @@ Topology NameToTopology(const std::string& name) {
return Topology::kUnknown;
}
+BlendFactor NameToBlendFactor(const std::string& name) {
+ if (name == "zero")
+ return BlendFactor::kZero;
+ else if (name == "one")
+ return BlendFactor::kOne;
+ else if (name == "src_color")
+ return BlendFactor::kSrcColor;
+ else if (name == "one_minus_src_color")
+ return BlendFactor::kOneMinusSrcColor;
+ else if (name == "dst_color")
+ return BlendFactor::kDstColor;
+ else if (name == "one_minus_dst_color")
+ return BlendFactor::kOneMinusDstColor;
+ else if (name == "src_alpha")
+ return BlendFactor::kSrcAlpha;
+ else if (name == "one_minus_src_alpha")
+ return BlendFactor::kOneMinusSrcAlpha;
+ else if (name == "dst_alpha")
+ return BlendFactor::kDstAlpha;
+ else if (name == "one_minus_dst_alpha")
+ return BlendFactor::kOneMinusDstAlpha;
+ else if (name == "constant_color")
+ return BlendFactor::kConstantColor;
+ else if (name == "one_minus_constant_color")
+ return BlendFactor::kOneMinusConstantColor;
+ else if (name == "costant_alpha")
+ return BlendFactor::kConstantAlpha;
+ else if (name == "one_minus_constant_alpha")
+ return BlendFactor::kOneMinusConstantAlpha;
+ else if (name == "src_alpha_saturate")
+ return BlendFactor::kSrcAlphaSaturate;
+ else if (name == "src1_color")
+ return BlendFactor::kSrc1Color;
+ else if (name == "one_minus_src1_color")
+ return BlendFactor::kOneMinusSrc1Color;
+ else if (name == "src1_alpha")
+ return BlendFactor::kSrc1Alpha;
+ else if (name == "one_minus_src1_alpha")
+ return BlendFactor::kOneMinusSrc1Alpha;
+ else
+ return BlendFactor::kUnknown;
+}
+
+BlendOp NameToBlendOp(const std::string& name) {
+ if (name == "add")
+ return BlendOp::kAdd;
+ else if (name == "substract")
+ return BlendOp::kSubtract;
+ else if (name == "reverse_substract")
+ return BlendOp::kReverseSubtract;
+ else if (name == "min")
+ return BlendOp::kMin;
+ else if (name == "max")
+ return BlendOp::kMax;
+ else if (name == "zero")
+ return BlendOp::kZero;
+ else if (name == "src")
+ return BlendOp::kSrc;
+ else if (name == "dst")
+ return BlendOp::kDst;
+ else if (name == "src_over")
+ return BlendOp::kSrcOver;
+ else if (name == "dst_over")
+ return BlendOp::kDstOver;
+ else if (name == "src_in")
+ return BlendOp::kSrcIn;
+ else if (name == "dst_in")
+ return BlendOp::kDstIn;
+ else if (name == "src_out")
+ return BlendOp::kSrcOut;
+ else if (name == "dst_out")
+ return BlendOp::kDstOut;
+ else if (name == "src_atop")
+ return BlendOp::kSrcAtop;
+ else if (name == "dst_atop")
+ return BlendOp::kDstAtop;
+ else if (name == "xor")
+ return BlendOp::kXor;
+ else if (name == "multiply")
+ return BlendOp::kMultiply;
+ else if (name == "screen")
+ return BlendOp::kScreen;
+ else if (name == "overlay")
+ return BlendOp::kOverlay;
+ else if (name == "darken")
+ return BlendOp::kDarken;
+ else if (name == "lighten")
+ return BlendOp::kLighten;
+ else if (name == "color_dodge")
+ return BlendOp::kColorDodge;
+ else if (name == "color_burn")
+ return BlendOp::kColorBurn;
+ else if (name == "hard_light")
+ return BlendOp::kHardLight;
+ else if (name == "soft_light")
+ return BlendOp::kSoftLight;
+ else if (name == "difference")
+ return BlendOp::kDifference;
+ else if (name == "exclusion")
+ return BlendOp::kExclusion;
+ else if (name == "invert")
+ return BlendOp::kInvert;
+ else if (name == "invert_rgb")
+ return BlendOp::kInvertRGB;
+ else if (name == "linear_dodge")
+ return BlendOp::kLinearDodge;
+ else if (name == "linear_burn")
+ return BlendOp::kLinearBurn;
+ else if (name == "vivid_light")
+ return BlendOp::kVividLight;
+ else if (name == "linear_light")
+ return BlendOp::kLinearLight;
+ else if (name == "pin_light")
+ return BlendOp::kPinLight;
+ else if (name == "hard_mix")
+ return BlendOp::kHardMix;
+ else if (name == "hsl_hue")
+ return BlendOp::kHslHue;
+ else if (name == "hsl_saturation")
+ return BlendOp::kHslSaturation;
+ else if (name == "hsl_color")
+ return BlendOp::kHslColor;
+ else if (name == "hsl_luminosity")
+ return BlendOp::kHslLuminosity;
+ else if (name == "plus")
+ return BlendOp::kPlus;
+ else if (name == "plus_clamped")
+ return BlendOp::kPlusClamped;
+ else if (name == "plus_clamped_alpha")
+ return BlendOp::kPlusClampedAlpha;
+ else if (name == "plus_darker")
+ return BlendOp::kPlusDarker;
+ else if (name == "minus")
+ return BlendOp::kMinus;
+ else if (name == "minus_clamped")
+ return BlendOp::kMinusClamped;
+ else if (name == "contrast")
+ return BlendOp::kContrast;
+ else if (name == "invert_ovg")
+ return BlendOp::kInvertOvg;
+ else if (name == "red")
+ return BlendOp::kRed;
+ else if (name == "green")
+ return BlendOp::kGreen;
+ else if (name == "blue")
+ return BlendOp::kBlue;
+ else
+ return BlendOp::kUnknown;
+}
+
} // namespace amber
diff --git a/src/command_data.h b/src/command_data.h
index 98ec405..f7e82a2 100644
--- a/src/command_data.h
+++ b/src/command_data.h
@@ -104,7 +104,8 @@ enum class LogicOp : uint8_t {
};
enum class BlendOp : uint8_t {
- kAdd = 0,
+ kUnknown = 0,
+ kAdd,
kSubtract,
kReverseSubtract,
kMin,
@@ -158,7 +159,8 @@ enum class BlendOp : uint8_t {
};
enum class BlendFactor : uint8_t {
- kZero = 0,
+ kUnknown = 0,
+ kZero,
kOne,
kSrcColor,
kOneMinusSrcColor,
@@ -180,6 +182,8 @@ enum class BlendFactor : uint8_t {
};
Topology NameToTopology(const std::string& name);
+BlendFactor NameToBlendFactor(const std::string& name);
+BlendOp NameToBlendOp(const std::string& name);
} // namespace amber
diff --git a/src/pipeline.cc b/src/pipeline.cc
index 9b73041..ae3bf0a 100644
--- a/src/pipeline.cc
+++ b/src/pipeline.cc
@@ -389,6 +389,18 @@ Result Pipeline::AddColorAttachment(Buffer* buf,
return {};
}
+Result Pipeline::AddResolveTarget(Buffer* buf) {
+ resolve_targets_.push_back(BufferInfo{buf});
+
+ auto& info = resolve_targets_.back();
+ info.type = BufferType::kResolve;
+ buf->SetWidth(fb_width_);
+ buf->SetHeight(fb_height_);
+ buf->SetElementCount(fb_width_ * fb_height_);
+
+ return {};
+}
+
Result Pipeline::GetLocationForColorAttachment(Buffer* buf,
uint32_t* loc) const {
for (const auto& info : color_attachments_) {
diff --git a/src/pipeline.h b/src/pipeline.h
index 7a80ad4..9010c59 100644
--- a/src/pipeline.h
+++ b/src/pipeline.h
@@ -303,6 +303,14 @@ class Pipeline {
/// something goes wrong.
Result GetLocationForColorAttachment(Buffer* buf, uint32_t* loc) const;
+ /// Returns a list of all resolve targets in this pipeline.
+ const std::vector<BufferInfo>& GetResolveTargets() const {
+ return resolve_targets_;
+ }
+
+ /// Adds |buf| as a multisample resolve target in the pipeline.
+ Result AddResolveTarget(Buffer* buf);
+
/// Sets |buf| as the depth/stencil buffer for this pipeline.
Result SetDepthStencilBuffer(Buffer* buf);
/// Returns information on the depth/stencil buffer bound to the pipeline. If
@@ -436,6 +444,7 @@ class Pipeline {
std::string name_;
std::vector<ShaderInfo> shaders_;
std::vector<BufferInfo> color_attachments_;
+ std::vector<BufferInfo> resolve_targets_;
std::vector<BufferInfo> vertex_buffers_;
std::vector<BufferInfo> buffers_;
std::vector<std::unique_ptr<type::Type>> types_;
diff --git a/src/pipeline_data.h b/src/pipeline_data.h
index 9a3b4d1..c763f37 100644
--- a/src/pipeline_data.h
+++ b/src/pipeline_data.h
@@ -178,6 +178,11 @@ class PipelineData {
bool HasViewportData() const { return has_viewport_data; }
const Viewport& GetViewport() const { return vp; }
+ void SetPatchControlPoints(uint32_t control_points) {
+ patch_control_points_ = control_points;
+ }
+ uint32_t GetPatchControlPoints() const { return patch_control_points_; }
+
private:
StencilOp front_fail_op_ = StencilOp::kKeep;
StencilOp front_pass_op_ = StencilOp::kKeep;
@@ -233,6 +238,8 @@ class PipelineData {
bool has_viewport_data = false;
Viewport vp;
+
+ uint32_t patch_control_points_ = 3u;
};
} // namespace amber
diff --git a/src/script.cc b/src/script.cc
index 7d7483f..8da8f11 100644
--- a/src/script.cc
+++ b/src/script.cc
@@ -114,7 +114,21 @@ bool Script::IsKnownFeature(const std::string& name) const {
name == "Storage16BitFeatures.storagePushConstant16" ||
name == "Storage16BitFeatures.storageInputOutput16" ||
name == "SubgroupSizeControl.subgroupSizeControl" ||
- name == "SubgroupSizeControl.computeFullSubgroups";
+ name == "SubgroupSizeControl.computeFullSubgroups" ||
+ name == "SubgroupSupportedOperations.basic" ||
+ name == "SubgroupSupportedOperations.vote" ||
+ name == "SubgroupSupportedOperations.arithmetic" ||
+ name == "SubgroupSupportedOperations.ballot" ||
+ name == "SubgroupSupportedOperations.shuffle" ||
+ name == "SubgroupSupportedOperations.shuffleRelative" ||
+ name == "SubgroupSupportedOperations.clustered" ||
+ name == "SubgroupSupportedOperations.quad" ||
+ name == "SubgroupSupportedStages.vertex" ||
+ name == "SubgroupSupportedStages.tessellationControl" ||
+ name == "SubgroupSupportedStages.tessellationEvaluation" ||
+ name == "SubgroupSupportedStages.geometry" ||
+ name == "SubgroupSupportedStages.fragment" ||
+ name == "SubgroupSupportedStages.compute";
}
type::Type* Script::ParseType(const std::string& str) {
diff --git a/src/vulkan/CMakeLists.txt b/src/vulkan/CMakeLists.txt
index b633c71..37bdd1f 100644
--- a/src/vulkan/CMakeLists.txt
+++ b/src/vulkan/CMakeLists.txt
@@ -43,6 +43,13 @@ target_include_directories(libamberenginevulkan PRIVATE "${CMAKE_BINARY_DIR}")
# Add the Vulkan include directory to the list of include paths.
target_include_directories(libamberenginevulkan PRIVATE "${VulkanHeaders_INCLUDE_DIR}")
+# When building with dEQP Vulkan CTS the inl files needs to be included and a dependency
+# must be added to the target `deqp-vk-inl` that generates the inl files.
+if (${VULKAN_CTS_HEADER} AND DEFINED AMBER_CTS_INL_DIR)
+ target_include_directories(libamberenginevulkan PRIVATE "${AMBER_CTS_INL_DIR}")
+ add_dependencies(libamberenginevulkan deqp-vk-inl)
+endif()
+
set_target_properties(libamberenginevulkan PROPERTIES
OUTPUT_NAME "amberenginevulkan"
)
@@ -52,7 +59,7 @@ endif()
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
# vulkan/vulkan.h defines VK_NULL_HANDLE as 0u and that also serves as a null pointer.
- # Disable Clang's warning that will alwaays fire on that. This is required to build
+ # Disable Clang's warning that will always fire on that. This is required to build
# with XCode 10.
target_compile_options(libamberenginevulkan PRIVATE -Wno-zero-as-null-pointer-constant)
endif()
diff --git a/src/vulkan/buffer_backed_descriptor.cc b/src/vulkan/buffer_backed_descriptor.cc
index d1b1aed..a2e874d 100644
--- a/src/vulkan/buffer_backed_descriptor.cc
+++ b/src/vulkan/buffer_backed_descriptor.cc
@@ -26,79 +26,65 @@ BufferBackedDescriptor::BufferBackedDescriptor(Buffer* buffer,
DescriptorType type,
Device* device,
uint32_t desc_set,
- uint32_t binding)
- : Descriptor(type, device, desc_set, binding) {
+ uint32_t binding,
+ Pipeline* pipeline)
+ : Descriptor(type, device, desc_set, binding), pipeline_(pipeline) {
AddAmberBuffer(buffer);
}
BufferBackedDescriptor::~BufferBackedDescriptor() = default;
-Result BufferBackedDescriptor::RecordCopyDataToResourceIfNeeded(
- CommandBuffer* command) {
- for (const auto& resource : GetResources()) {
- if (!resource.first->ValuePtr()->empty()) {
- resource.second->UpdateMemoryWithRawData(*resource.first->ValuePtr());
- // If the resource is read-only, keep the buffer data; Amber won't copy
- // read-only resources back into the host buffers, so it makes sense to
- // leave the buffer intact.
- if (!IsReadOnly())
- resource.first->ValuePtr()->clear();
- }
-
- resource.second->CopyToDevice(command);
- }
+Result BufferBackedDescriptor::RecordCopyBufferDataToTransferResourceIfNeeded(
+ CommandBuffer* command_buffer,
+ Buffer* buffer,
+ Resource* transfer_resource) {
+ transfer_resource->UpdateMemoryWithRawData(*buffer->ValuePtr());
+ // If the resource is read-only, keep the buffer data; Amber won't copy
+ // read-only resources back into the host buffers, so it makes sense to
+ // leave the buffer intact.
+ if (!transfer_resource->IsReadOnly())
+ buffer->ValuePtr()->clear();
+
+ transfer_resource->CopyToDevice(command_buffer);
return {};
}
-Result BufferBackedDescriptor::RecordCopyDataToHost(CommandBuffer* command) {
- if (!IsReadOnly()) {
- if (GetResources().empty()) {
- return Result(
- "Vulkan: BufferBackedDescriptor::RecordCopyDataToHost() no transfer "
- "resources");
- }
-
- for (const auto& r : GetResources())
- r.second->CopyToHost(command);
+Result BufferBackedDescriptor::RecordCopyTransferResourceToHost(
+ CommandBuffer* command_buffer,
+ Resource* transfer_resource) {
+ if (!transfer_resource->IsReadOnly()) {
+ transfer_resource->CopyToHost(command_buffer);
}
return {};
}
-Result BufferBackedDescriptor::MoveResourceToBufferOutput() {
- // No need to copy results of read only resources.
- if (IsReadOnly())
+Result BufferBackedDescriptor::MoveTransferResourceToBufferOutput(
+ Resource* transfer_resource,
+ Buffer* buffer) {
+ // No need to move read only resources to an output buffer.
+ if (transfer_resource->IsReadOnly()) {
return {};
+ }
- auto resources = GetResources();
-
- if (resources.empty()) {
+ void* resource_memory_ptr = transfer_resource->HostAccessibleMemoryPtr();
+ if (!resource_memory_ptr) {
return Result(
- "Vulkan: BufferBackedDescriptor::MoveResourceToBufferOutput() no "
- "transfer resource");
+ "Vulkan: BufferBackedDescriptor::MoveTransferResourceToBufferOutput() "
+ "no host accessible memory pointer");
}
- for (const auto& resource : resources) {
- void* resource_memory_ptr = resource.second->HostAccessibleMemoryPtr();
- auto* buffer = resource.first;
- if (!resource_memory_ptr) {
- return Result(
- "Vulkan: BufferBackedDescriptor::MoveResourceToBufferOutput() "
- "no host accessible memory pointer");
- }
-
- if (!buffer->ValuePtr()->empty()) {
- return Result(
- "Vulkan: BufferBackedDescriptor::MoveResourceToBufferOutput() "
- "output buffer is not empty");
- }
-
- auto size_in_bytes = resource.second->GetSizeInBytes();
- buffer->SetElementCount(size_in_bytes / buffer->GetFormat()->SizeInBytes());
- buffer->ValuePtr()->resize(size_in_bytes);
- std::memcpy(buffer->ValuePtr()->data(), resource_memory_ptr, size_in_bytes);
+ if (!buffer->ValuePtr()->empty()) {
+ return Result(
+ "Vulkan: BufferBackedDescriptor::MoveTransferResourceToBufferOutput() "
+ "output buffer is not empty");
}
+ auto size_in_bytes = transfer_resource->GetSizeInBytes();
+ buffer->SetElementCount(size_in_bytes / buffer->GetFormat()->SizeInBytes());
+ buffer->ValuePtr()->resize(size_in_bytes);
+ std::memcpy(buffer->ValuePtr()->data(), resource_memory_ptr, size_in_bytes);
+
return {};
}
diff --git a/src/vulkan/buffer_backed_descriptor.h b/src/vulkan/buffer_backed_descriptor.h
index 8f9df41..8a2d0a5 100644
--- a/src/vulkan/buffer_backed_descriptor.h
+++ b/src/vulkan/buffer_backed_descriptor.h
@@ -25,6 +25,7 @@
#include "src/buffer.h"
#include "src/engine.h"
#include "src/vulkan/descriptor.h"
+#include "src/vulkan/pipeline.h"
#include "src/vulkan/resource.h"
namespace amber {
@@ -36,13 +37,19 @@ class BufferBackedDescriptor : public Descriptor {
DescriptorType type,
Device* device,
uint32_t desc_set,
- uint32_t binding);
+ uint32_t binding,
+ Pipeline* pipeline);
~BufferBackedDescriptor() override;
Result CreateResourceIfNeeded() override { return {}; }
- Result RecordCopyDataToResourceIfNeeded(CommandBuffer* command) override;
- Result RecordCopyDataToHost(CommandBuffer* command) override;
- Result MoveResourceToBufferOutput() override;
+ static Result RecordCopyBufferDataToTransferResourceIfNeeded(
+ CommandBuffer* command_buffer,
+ Buffer* buffer,
+ Resource* transfer_resource);
+ static Result RecordCopyTransferResourceToHost(CommandBuffer* command_buffer,
+ Resource* transfer_resource);
+ static Result MoveTransferResourceToBufferOutput(Resource* transfer_resource,
+ Buffer* buffer);
uint32_t GetDescriptorCount() override {
return static_cast<uint32_t>(amber_buffers_.size());
}
@@ -52,10 +59,8 @@ class BufferBackedDescriptor : public Descriptor {
bool IsReadOnly() const;
protected:
- /// Returns a list of unique transfer buffer resources. Note that this list
- /// may contain less items than the |amber_buffers| vector contains if two or
- /// more amber buffers use same Vulkan buffer.
- virtual std::vector<std::pair<Buffer*, Resource*>> GetResources() = 0;
+ // Pipeline where this descriptor is attached to.
+ Pipeline* pipeline_;
private:
std::vector<Buffer*> amber_buffers_;
diff --git a/src/vulkan/buffer_descriptor.cc b/src/vulkan/buffer_descriptor.cc
index aa8b2dd..d60ce08 100644
--- a/src/vulkan/buffer_descriptor.cc
+++ b/src/vulkan/buffer_descriptor.cc
@@ -29,65 +29,63 @@ BufferDescriptor::BufferDescriptor(Buffer* buffer,
DescriptorType type,
Device* device,
uint32_t desc_set,
- uint32_t binding)
- : BufferBackedDescriptor(buffer, type, device, desc_set, binding) {}
+ uint32_t binding,
+ Pipeline* pipeline)
+ : BufferBackedDescriptor(buffer,
+ type,
+ device,
+ desc_set,
+ binding,
+ pipeline) {}
BufferDescriptor::~BufferDescriptor() = default;
Result BufferDescriptor::CreateResourceIfNeeded() {
- if (!transfer_buffers_.empty()) {
- return Result(
- "Vulkan: BufferDescriptor::CreateResourceIfNeeded() must be called "
- "only when |transfer_buffers| is empty");
+ auto& transfer_resources = pipeline_->GetDescriptorTransferResources();
+
+ VkBufferUsageFlags flags =
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ if (IsUniformBuffer() || IsUniformBufferDynamic()) {
+ flags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ } else if (IsStorageBuffer() || IsStorageBufferDynamic()) {
+ flags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ } else if (IsUniformTexelBuffer()) {
+ flags |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+ } else if (IsStorageTexelBuffer()) {
+ flags |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
+ } else {
+ return Result("Unexpected buffer type when deciding usage flags");
}
- descriptor_offsets_.reserve(GetAmberBuffers().size());
- descriptor_ranges_.reserve(GetAmberBuffers().size());
-
for (const auto& amber_buffer : GetAmberBuffers()) {
- if (amber_buffer->ValuePtr()->empty())
- continue;
-
- // Check if the transfer buffer is already created.
- if (transfer_buffers_.count(amber_buffer) > 0)
- continue;
-
- auto size_in_bytes =
- static_cast<uint32_t>(amber_buffer->ValuePtr()->size());
-
- auto transfer_buffer = MakeUnique<TransferBuffer>(
- device_, size_in_bytes, amber_buffer->GetFormat());
-
- VkBufferUsageFlags flags =
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- if (IsUniformBuffer() || IsUniformBufferDynamic()) {
- flags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
- } else if (IsStorageBuffer() || IsStorageBufferDynamic()) {
- flags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
- } else if (IsUniformTexelBuffer()) {
- flags |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
- } else if (IsStorageTexelBuffer()) {
- flags |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
+ // Create (but don't initialize) the transfer buffer if not already created.
+ if (transfer_resources.count(amber_buffer) == 0) {
+ auto size_in_bytes =
+ static_cast<uint32_t>(amber_buffer->ValuePtr()->size());
+ auto transfer_buffer = MakeUnique<TransferBuffer>(
+ device_, size_in_bytes, amber_buffer->GetFormat());
+ transfer_buffer->SetReadOnly(IsReadOnly());
+ transfer_resources[amber_buffer] = std::move(transfer_buffer);
} else {
- return Result("Unexpected buffer type when deciding usage flags");
+ // Unset transfer buffer's read only property if needed.
+ if (!IsReadOnly()) {
+ transfer_resources[amber_buffer]->SetReadOnly(false);
+ }
}
- Result r = transfer_buffer->Initialize(flags);
+ // Update the buffer create flags.
+ Result r =
+ transfer_resources[amber_buffer]->AsTransferBuffer()->AddUsageFlags(
+ flags);
if (!r.IsSuccess())
return r;
- transfer_buffers_[amber_buffer] = std::move(transfer_buffer);
}
-
is_descriptor_set_update_needed_ = true;
- return {};
-}
-
-Result BufferDescriptor::MoveResourceToBufferOutput() {
- Result r = BufferBackedDescriptor::MoveResourceToBufferOutput();
- transfer_buffers_.clear();
+ descriptor_offsets_.reserve(GetAmberBuffers().size());
+ descriptor_ranges_.reserve(GetAmberBuffers().size());
- return r;
+ return {};
}
void BufferDescriptor::UpdateDescriptorSetIfNeeded(
@@ -100,7 +98,9 @@ void BufferDescriptor::UpdateDescriptorSetIfNeeded(
// Create VkDescriptorBufferInfo for every descriptor buffer.
for (uint32_t i = 0; i < GetAmberBuffers().size(); i++) {
- const auto& buffer = transfer_buffers_[GetAmberBuffers()[i]];
+ const auto& buffer =
+ pipeline_->GetDescriptorTransferResources()[GetAmberBuffers()[i]]
+ ->AsTransferBuffer();
assert(buffer->GetVkBuffer() && "Unexpected descriptor type");
// Add buffer infos for uniform and storage buffers.
if (IsUniformBuffer() || IsUniformBufferDynamic() || IsStorageBuffer() ||
@@ -146,23 +146,5 @@ void BufferDescriptor::UpdateDescriptorSetIfNeeded(
is_descriptor_set_update_needed_ = false;
}
-std::vector<std::pair<Buffer*, Resource*>> BufferDescriptor::GetResources() {
- std::vector<std::pair<Buffer*, Resource*>> ret;
- // Add unique amber buffers and related transfer buffers to the vector.
- for (const auto& amber_buffer : GetAmberBuffers()) {
- // Skip duplicate values.
- const auto& image =
- std::find_if(ret.begin(), ret.end(),
- [&](const std::pair<Buffer*, Resource*>& buffer) {
- return buffer.first == amber_buffer;
- });
- if (image != ret.end())
- continue;
-
- ret.emplace_back(amber_buffer, transfer_buffers_[amber_buffer].get());
- }
- return ret;
-}
-
} // namespace vulkan
} // namespace amber
diff --git a/src/vulkan/buffer_descriptor.h b/src/vulkan/buffer_descriptor.h
index 2c3f390..439afa5 100644
--- a/src/vulkan/buffer_descriptor.h
+++ b/src/vulkan/buffer_descriptor.h
@@ -26,6 +26,7 @@
#include "src/buffer.h"
#include "src/engine.h"
#include "src/vulkan/buffer_backed_descriptor.h"
+#include "src/vulkan/pipeline.h"
#include "src/vulkan/transfer_buffer.h"
namespace amber {
@@ -42,12 +43,12 @@ class BufferDescriptor : public BufferBackedDescriptor {
DescriptorType type,
Device* device,
uint32_t desc_set,
- uint32_t binding);
+ uint32_t binding,
+ vulkan::Pipeline* pipeline);
~BufferDescriptor() override;
void UpdateDescriptorSetIfNeeded(VkDescriptorSet descriptor_set) override;
Result CreateResourceIfNeeded() override;
- Result MoveResourceToBufferOutput() override;
std::vector<uint32_t> GetDynamicOffsets() override {
return dynamic_offsets_;
}
@@ -67,12 +68,7 @@ class BufferDescriptor : public BufferBackedDescriptor {
BufferDescriptor* AsBufferDescriptor() override { return this; }
- protected:
- std::vector<std::pair<Buffer*, Resource*>> GetResources() override;
-
private:
- std::unordered_map<Buffer*, std::unique_ptr<TransferBuffer>>
- transfer_buffers_;
std::vector<uint32_t> dynamic_offsets_;
std::vector<VkDeviceSize> descriptor_offsets_;
std::vector<VkDeviceSize> descriptor_ranges_;
diff --git a/src/vulkan/command_buffer.cc b/src/vulkan/command_buffer.cc
index 2843667..765ef94 100644
--- a/src/vulkan/command_buffer.cc
+++ b/src/vulkan/command_buffer.cc
@@ -108,7 +108,6 @@ Result CommandBuffer::SubmitAndReset(uint32_t timeout_ms) {
void CommandBuffer::Reset() {
if (guarded_) {
- device_->GetPtrs()->vkEndCommandBuffer(command_);
device_->GetPtrs()->vkResetCommandBuffer(command_, 0);
guarded_ = false;
}
diff --git a/src/vulkan/descriptor.h b/src/vulkan/descriptor.h
index 03434a3..88f6813 100644
--- a/src/vulkan/descriptor.h
+++ b/src/vulkan/descriptor.h
@@ -31,6 +31,7 @@ namespace vulkan {
class CommandBuffer;
class Device;
class BufferDescriptor;
+class ImageDescriptor;
class BufferBackedDescriptor;
class SamplerDescriptor;
@@ -57,16 +58,12 @@ class Descriptor {
virtual void UpdateDescriptorSetIfNeeded(VkDescriptorSet descriptor_set) = 0;
virtual Result CreateResourceIfNeeded() = 0;
- virtual Result RecordCopyDataToResourceIfNeeded(CommandBuffer*) { return {}; }
- virtual Result RecordCopyDataToHost(CommandBuffer*) { return {}; }
- virtual Result MoveResourceToBufferOutput() { return {}; }
- virtual Result SetSizeInElements(uint32_t) { return {}; }
- virtual Result AddToBuffer(const std::vector<Value>&, uint32_t) { return {}; }
virtual uint32_t GetDescriptorCount() { return 1; }
virtual std::vector<uint32_t> GetDynamicOffsets() { return {}; }
virtual std::vector<VkDeviceSize> GetDescriptorOffsets() { return {}; }
virtual std::vector<VkDeviceSize> GetDescriptorRanges() { return {}; }
virtual BufferDescriptor* AsBufferDescriptor() { return nullptr; }
+ virtual ImageDescriptor* AsImageDescriptor() { return nullptr; }
virtual BufferBackedDescriptor* AsBufferBackedDescriptor() { return nullptr; }
virtual SamplerDescriptor* AsSamplerDescriptor() { return nullptr; }
uint32_t GetDescriptorSet() const { return descriptor_set_; }
diff --git a/src/vulkan/device.cc b/src/vulkan/device.cc
index 22cd77a..d951f49 100644
--- a/src/vulkan/device.cc
+++ b/src/vulkan/device.cc
@@ -53,6 +53,36 @@ const char k16BitStorage_InputOutput[] =
const char kSubgroupSizeControl[] = "SubgroupSizeControl.subgroupSizeControl";
const char kComputeFullSubgroups[] = "SubgroupSizeControl.computeFullSubgroups";
+const char kSubgroupSupportedOperations[] = "SubgroupSupportedOperations";
+const char kSubgroupSupportedOperationsBasic[] =
+ "SubgroupSupportedOperations.basic";
+const char kSubgroupSupportedOperationsVote[] =
+ "SubgroupSupportedOperations.vote";
+const char kSubgroupSupportedOperationsArithmetic[] =
+ "SubgroupSupportedOperations.arithmetic";
+const char kSubgroupSupportedOperationsBallot[] =
+ "SubgroupSupportedOperations.ballot";
+const char kSubgroupSupportedOperationsShuffle[] =
+ "SubgroupSupportedOperations.shuffle";
+const char kSubgroupSupportedOperationsShuffleRelative[] =
+ "SubgroupSupportedOperations.shuffleRelative";
+const char kSubgroupSupportedOperationsClustered[] =
+ "SubgroupSupportedOperations.clustered";
+const char kSubgroupSupportedOperationsQuad[] =
+ "SubgroupSupportedOperations.quad";
+const char kSubgroupSupportedStages[] = "SubgroupSupportedStages";
+const char kSubgroupSupportedStagesVertex[] = "SubgroupSupportedStages.vertex";
+const char kSubgroupSupportedStagesTessellationControl[] =
+ "SubgroupSupportedStages.tessellationControl";
+const char kSubgroupSupportedStagesTessellationEvaluation[] =
+ "SubgroupSupportedStages.tessellationEvaluation";
+const char kSubgroupSupportedStagesGeometry[] =
+ "SubgroupSupportedStages.geometry";
+const char kSubgroupSupportedStagesFragment[] =
+ "SubgroupSupportedStages.fragment";
+const char kSubgroupSupportedStagesCompute[] =
+ "SubgroupSupportedStages.compute";
+
struct BaseOutStructure {
VkStructureType sType;
void* pNext;
@@ -437,6 +467,7 @@ Result Device::Initialize(
VkPhysicalDevice16BitStorageFeaturesKHR* storage16_ptrs = nullptr;
VkPhysicalDeviceVulkan11Features* vulkan11_ptrs = nullptr;
VkPhysicalDeviceVulkan12Features* vulkan12_ptrs = nullptr;
+ VkPhysicalDeviceVulkan13Features* vulkan13_ptrs = nullptr;
VkPhysicalDeviceSubgroupSizeControlFeaturesEXT*
subgroup_size_control_features = nullptr;
void* ptr = available_features2.pNext;
@@ -469,6 +500,9 @@ Result Device::Initialize(
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES:
vulkan12_ptrs = static_cast<VkPhysicalDeviceVulkan12Features*>(ptr);
break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES:
+ vulkan13_ptrs = static_cast<VkPhysicalDeviceVulkan13Features*>(ptr);
+ break;
default:
break;
}
@@ -513,7 +547,7 @@ Result Device::Initialize(
"Shader 8-bit storage requested but feature not returned");
}
if ((feature == kSubgroupSizeControl || feature == kComputeFullSubgroups) &&
- subgroup_size_control_features == nullptr) {
+ subgroup_size_control_features == nullptr && vulkan13_ptrs == nullptr) {
return amber::Result("Missing subgroup size control features");
}
@@ -622,13 +656,25 @@ Result Device::Initialize(
}
}
- if (feature == kSubgroupSizeControl &&
- subgroup_size_control_features->subgroupSizeControl != VK_TRUE) {
- return amber::Result("Missing subgroup size control feature");
- }
- if (feature == kComputeFullSubgroups &&
- subgroup_size_control_features->computeFullSubgroups != VK_TRUE) {
- return amber::Result("Missing compute full subgroups feature");
+ // If Vulkan 1.3 structure exists the features are set there.
+ if (vulkan13_ptrs) {
+ if (feature == kSubgroupSizeControl &&
+ vulkan13_ptrs->subgroupSizeControl != VK_TRUE) {
+ return amber::Result("Missing subgroup size control feature");
+ }
+ if (feature == kComputeFullSubgroups &&
+ vulkan13_ptrs->computeFullSubgroups != VK_TRUE) {
+ return amber::Result("Missing compute full subgroups feature");
+ }
+ } else {
+ if (feature == kSubgroupSizeControl &&
+ subgroup_size_control_features->subgroupSizeControl != VK_TRUE) {
+ return amber::Result("Missing subgroup size control feature");
+ }
+ if (feature == kComputeFullSubgroups &&
+ subgroup_size_control_features->computeFullSubgroups != VK_TRUE) {
+ return amber::Result("Missing compute full subgroups feature");
+ }
}
}
@@ -647,19 +693,153 @@ Result Device::Initialize(
std::find(required_features.begin(), required_features.end(),
kSubgroupSizeControl) != required_features.end();
- if (needs_subgroup_size_control) {
+ bool needs_subgroup_supported_operations = false;
+ bool needs_subgroup_supported_stages = false;
+
+ // Search for subgroup supported operations requirements.
+ for (const auto& feature : required_features)
+ if (feature.find(kSubgroupSupportedOperations) != std::string::npos)
+ needs_subgroup_supported_operations = true;
+
+ // Search for subgroup supported stages requirements.
+ for (const auto& feature : required_features)
+ if (feature.find(kSubgroupSupportedStages) != std::string::npos)
+ needs_subgroup_supported_stages = true;
+
+ const bool needs_subgroup_properties =
+ needs_subgroup_supported_operations || needs_subgroup_supported_stages;
+
+ if (needs_subgroup_size_control || needs_subgroup_properties) {
+ // Always chain all physical device properties structs in case at least one
+ // of them is needed.
VkPhysicalDeviceProperties2 properties2 = {};
+ VkPhysicalDeviceSubgroupProperties subgroup_properties = {};
+ VkPhysicalDeviceVulkan11Properties vulkan11_properties = {};
+ VkSubgroupFeatureFlags subgroup_supported_operations;
+ VkShaderStageFlags subgroup_supported_stages;
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties2.pNext = &subgroup_size_control_properties_;
subgroup_size_control_properties_.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT;
+ if (SupportsApiVersion(1, 2, 0)) {
+ subgroup_size_control_properties_.pNext = &vulkan11_properties;
+ vulkan11_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
+ } else {
+ subgroup_size_control_properties_.pNext = &subgroup_properties;
+ subgroup_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ }
- if (!SupportsApiVersion(1, 1, 0)) {
+ if (needs_subgroup_size_control && !SupportsApiVersion(1, 1, 0)) {
return Result(
"Vulkan: Device::Initialize subgroup size control feature also "
"requires an API version of 1.1 or higher");
}
+ if (needs_subgroup_properties && !SupportsApiVersion(1, 1, 0)) {
+ return Result(
+ "Vulkan: Device::Initialize subgroup properties also "
+ "requires an API version of 1.1 or higher");
+ }
ptrs_.vkGetPhysicalDeviceProperties2(physical_device_, &properties2);
+
+ if (needs_subgroup_supported_operations) {
+ // Read supported subgroup operations from the correct struct depending on
+ // the device API
+ if (SupportsApiVersion(1, 2, 0)) {
+ subgroup_supported_operations =
+ vulkan11_properties.subgroupSupportedOperations;
+ } else {
+ subgroup_supported_operations = subgroup_properties.supportedOperations;
+ }
+
+ for (const auto& feature : required_features) {
+ if (feature == kSubgroupSupportedOperationsBasic &&
+ !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_BASIC_BIT)) {
+ return amber::Result("Missing subgroup operation basic feature");
+ }
+ if (feature == kSubgroupSupportedOperationsVote &&
+ !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_VOTE_BIT)) {
+ return amber::Result("Missing subgroup operation vote feature");
+ }
+ if (feature == kSubgroupSupportedOperationsArithmetic &&
+ !(subgroup_supported_operations &
+ VK_SUBGROUP_FEATURE_ARITHMETIC_BIT)) {
+ return amber::Result("Missing subgroup operation arithmetic feature");
+ }
+ if (feature == kSubgroupSupportedOperationsBallot &&
+ !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_BALLOT_BIT)) {
+ return amber::Result("Missing subgroup operation ballot feature");
+ }
+ if (feature == kSubgroupSupportedOperationsShuffle &&
+ !(subgroup_supported_operations &
+ VK_SUBGROUP_FEATURE_SHUFFLE_BIT)) {
+ return amber::Result("Missing subgroup operation shuffle feature");
+ }
+ if (feature == kSubgroupSupportedOperationsShuffleRelative &&
+ !(subgroup_supported_operations &
+ VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT)) {
+ return amber::Result(
+ "Missing subgroup operation shuffle relative feature");
+ }
+ if (feature == kSubgroupSupportedOperationsClustered &&
+ !(subgroup_supported_operations &
+ VK_SUBGROUP_FEATURE_CLUSTERED_BIT)) {
+ return amber::Result("Missing subgroup operation clustered feature");
+ }
+ if (feature == kSubgroupSupportedOperationsQuad &&
+ !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_QUAD_BIT)) {
+ return amber::Result("Missing subgroup operation quad feature");
+ }
+ }
+ }
+
+ if (needs_subgroup_supported_stages) {
+ // Read supported subgroup stages from the correct struct depending on the
+ // device API
+ if (SupportsApiVersion(1, 2, 0)) {
+ subgroup_supported_stages = vulkan11_properties.subgroupSupportedStages;
+ } else {
+ subgroup_supported_stages = subgroup_properties.supportedStages;
+ }
+
+ for (const auto& feature : required_features) {
+ if (feature == kSubgroupSupportedStagesVertex &&
+ !(subgroup_supported_stages & VK_SHADER_STAGE_VERTEX_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for vertex shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesTessellationControl &&
+ !(subgroup_supported_stages &
+ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for tessellation control "
+ "shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesTessellationEvaluation &&
+ !(subgroup_supported_stages &
+ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for tessellation evaluation "
+ "shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesGeometry &&
+ !(subgroup_supported_stages & VK_SHADER_STAGE_GEOMETRY_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for geometry shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesFragment &&
+ !(subgroup_supported_stages & VK_SHADER_STAGE_FRAGMENT_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for fragment shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesCompute &&
+ !(subgroup_supported_stages & VK_SHADER_STAGE_COMPUTE_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for compute shader stage");
+ }
+ }
+ }
}
return {};
@@ -676,6 +856,7 @@ bool Device::IsFormatSupportedByPhysicalDevice(const Format& format,
bool is_buffer_type_image = false;
switch (type) {
case BufferType::kColor:
+ case BufferType::kResolve:
case BufferType::kStorageImage:
flag = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
is_buffer_type_image = true;
diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc
index 6bed716..1ed60f4 100644
--- a/src/vulkan/engine_vulkan.cc
+++ b/src/vulkan/engine_vulkan.cc
@@ -177,8 +177,11 @@ Result EngineVulkan::CreatePipeline(amber::Pipeline* pipeline) {
} else {
vk_pipeline = MakeUnique<GraphicsPipeline>(
device_.get(), pipeline->GetColorAttachments(),
- pipeline->GetDepthStencilBuffer(), engine_data.fence_timeout_ms,
- stage_create_info);
+ pipeline->GetDepthStencilBuffer(), pipeline->GetResolveTargets(),
+ engine_data.fence_timeout_ms, stage_create_info);
+
+ vk_pipeline->AsGraphics()->SetPatchControlPoints(
+ pipeline->GetPipelineData()->GetPatchControlPoints());
r = vk_pipeline->AsGraphics()->Initialize(pipeline->GetFramebufferWidth(),
pipeline->GetFramebufferHeight(),
diff --git a/src/vulkan/frame_buffer.cc b/src/vulkan/frame_buffer.cc
index 47eb82d..b6ad13a 100644
--- a/src/vulkan/frame_buffer.cc
+++ b/src/vulkan/frame_buffer.cc
@@ -30,10 +30,12 @@ FrameBuffer::FrameBuffer(
Device* device,
const std::vector<const amber::Pipeline::BufferInfo*>& color_attachments,
amber::Pipeline::BufferInfo depth_stencil_attachment,
+ const std::vector<const amber::Pipeline::BufferInfo*>& resolve_targets,
uint32_t width,
uint32_t height)
: device_(device),
color_attachments_(color_attachments),
+ resolve_targets_(resolve_targets),
depth_stencil_attachment_(depth_stencil_attachment),
width_(width),
height_(height) {}
@@ -62,15 +64,16 @@ Result FrameBuffer::Initialize(VkRenderPass render_pass) {
attachments.resize(color_attachments_.size());
for (auto* info : color_attachments_) {
+ const VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
color_images_.push_back(MakeUnique<TransferImage>(
device_, *info->buffer->GetFormat(), VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_TYPE_2D, width_ << info->base_mip_level,
+ VK_IMAGE_TYPE_2D, usage_flags, width_ << info->base_mip_level,
height_ << info->base_mip_level, depth_, info->buffer->GetMipLevels(),
- info->base_mip_level, 1u, 1u));
+ info->base_mip_level, 1u, info->buffer->GetSamples()));
- Result r = color_images_.back()->Initialize(
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
- VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
+ Result r = color_images_.back()->Initialize();
if (!r.IsSuccess())
return r;
@@ -87,19 +90,37 @@ Result FrameBuffer::Initialize(VkRenderPass render_pass) {
aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
assert(aspect != 0);
+ const VkImageUsageFlags usage_flags =
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
depth_stencil_image_ = MakeUnique<TransferImage>(
device_, *depth_stencil_attachment_.buffer->GetFormat(), aspect,
- VK_IMAGE_TYPE_2D, width_, height_, depth_, 1u, 0u, 1u, 1u);
+ VK_IMAGE_TYPE_2D, usage_flags, width_, height_, depth_, 1u, 0u, 1u, 1u);
- Result r = depth_stencil_image_->Initialize(
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
- VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
+ Result r = depth_stencil_image_->Initialize();
if (!r.IsSuccess())
return r;
attachments.push_back(depth_stencil_image_->GetVkImageView());
}
+ for (auto* info : resolve_targets_) {
+ const VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ resolve_images_.push_back(MakeUnique<TransferImage>(
+ device_, *info->buffer->GetFormat(), VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_TYPE_2D, usage_flags, width_, height_, depth_, 1u, 0u, 1u,
+ 1u));
+
+ Result r = resolve_images_.back()->Initialize();
+ if (!r.IsSuccess())
+ return r;
+
+ attachments.push_back(resolve_images_.back()->GetVkImageView());
+ }
+
VkFramebufferCreateInfo frame_buffer_info = VkFramebufferCreateInfo();
frame_buffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
frame_buffer_info.renderPass = render_pass;
@@ -126,6 +147,9 @@ void FrameBuffer::ChangeFrameLayout(CommandBuffer* command,
for (auto& img : color_images_)
img->ImageBarrier(command, color_layout, color_stage);
+ for (auto& img : resolve_images_)
+ img->ImageBarrier(command, color_layout, color_stage);
+
if (depth_stencil_image_)
depth_stencil_image_->ImageBarrier(command, depth_layout, depth_stage);
}
@@ -162,6 +186,9 @@ void FrameBuffer::TransferImagesToHost(CommandBuffer* command) {
for (auto& img : color_images_)
img->CopyToHost(command);
+ for (auto& img : resolve_images_)
+ img->CopyToHost(command);
+
if (depth_stencil_image_)
depth_stencil_image_->CopyToHost(command);
}
@@ -176,6 +203,15 @@ void FrameBuffer::CopyImagesToBuffers() {
info->buffer->GetSizeInBytes());
}
+ for (size_t i = 0; i < resolve_images_.size(); ++i) {
+ auto& img = resolve_images_[i];
+ auto* info = resolve_targets_[i];
+ auto* values = info->buffer->ValuePtr();
+ values->resize(info->buffer->GetSizeInBytes());
+ std::memcpy(values->data(), img->HostAccessibleMemoryPtr(),
+ info->buffer->GetSizeInBytes());
+ }
+
if (depth_stencil_image_) {
auto* values = depth_stencil_attachment_.buffer->ValuePtr();
values->resize(depth_stencil_attachment_.buffer->GetSizeInBytes());
@@ -205,6 +241,18 @@ void FrameBuffer::CopyBuffersToImages() {
info->buffer->GetSizeInBytes());
}
+ for (size_t i = 0; i < resolve_images_.size(); ++i) {
+ auto& img = resolve_images_[i];
+ auto* info = resolve_targets_[i];
+ auto* values = info->buffer->ValuePtr();
+ // Nothing to do if our local buffer is empty
+ if (values->empty())
+ continue;
+
+ std::memcpy(img->HostAccessibleMemoryPtr(), values->data(),
+ info->buffer->GetSizeInBytes());
+ }
+
if (depth_stencil_image_) {
auto* values = depth_stencil_attachment_.buffer->ValuePtr();
// Nothing to do if our local buffer is empty
diff --git a/src/vulkan/frame_buffer.h b/src/vulkan/frame_buffer.h
index 064b6d3..5774289 100644
--- a/src/vulkan/frame_buffer.h
+++ b/src/vulkan/frame_buffer.h
@@ -34,6 +34,7 @@ class FrameBuffer {
Device* device,
const std::vector<const amber::Pipeline::BufferInfo*>& color_attachments,
amber::Pipeline::BufferInfo depth_stencil_attachment,
+ const std::vector<const amber::Pipeline::BufferInfo*>& resolve_targets,
uint32_t width,
uint32_t height);
~FrameBuffer();
@@ -70,9 +71,11 @@ class FrameBuffer {
Device* device_ = nullptr;
std::vector<const amber::Pipeline::BufferInfo*> color_attachments_;
+ std::vector<const amber::Pipeline::BufferInfo*> resolve_targets_;
amber::Pipeline::BufferInfo depth_stencil_attachment_;
VkFramebuffer frame_ = VK_NULL_HANDLE;
std::vector<std::unique_ptr<TransferImage>> color_images_;
+ std::vector<std::unique_ptr<TransferImage>> resolve_images_;
std::unique_ptr<TransferImage> depth_stencil_image_;
uint32_t width_ = 0;
uint32_t height_ = 0;
diff --git a/src/vulkan/graphics_pipeline.cc b/src/vulkan/graphics_pipeline.cc
index 5536440..138f32c 100644
--- a/src/vulkan/graphics_pipeline.cc
+++ b/src/vulkan/graphics_pipeline.cc
@@ -234,6 +234,8 @@ VkBlendFactor ToVkBlendFactor(BlendFactor factor) {
return VK_BLEND_FACTOR_SRC1_ALPHA;
case BlendFactor::kOneMinusSrc1Alpha:
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
+ case BlendFactor::kUnknown:
+ break;
}
assert(false && "Vulkan::Unknown BlendFactor");
return VK_BLEND_FACTOR_ZERO;
@@ -343,6 +345,8 @@ VkBlendOp ToVkBlendOp(BlendOp op) {
return VK_BLEND_OP_GREEN_EXT;
case BlendOp::kBlue:
return VK_BLEND_OP_BLUE_EXT;
+ case BlendOp::kUnknown:
+ break;
}
assert(false && "Vulkan::Unknown BlendOp");
return VK_BLEND_OP_ADD;
@@ -386,6 +390,7 @@ GraphicsPipeline::GraphicsPipeline(
Device* device,
const std::vector<amber::Pipeline::BufferInfo>& color_buffers,
amber::Pipeline::BufferInfo depth_stencil_buffer,
+ const std::vector<amber::Pipeline::BufferInfo>& resolve_targets,
uint32_t fence_timeout_ms,
const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info)
: Pipeline(PipelineType::kGraphics,
@@ -395,6 +400,8 @@ GraphicsPipeline::GraphicsPipeline(
depth_stencil_buffer_(depth_stencil_buffer) {
for (const auto& info : color_buffers)
color_buffers_.push_back(&info);
+ for (const auto& info : resolve_targets)
+ resolve_targets_.push_back(&info);
}
GraphicsPipeline::~GraphicsPipeline() {
@@ -412,6 +419,7 @@ Result GraphicsPipeline::CreateRenderPass() {
std::vector<VkAttachmentReference> color_refer;
VkAttachmentReference depth_refer = VkAttachmentReference();
+ std::vector<VkAttachmentReference> resolve_refer;
for (const auto* info : color_buffers_) {
attachment_desc.push_back(kDefaultAttachmentDesc);
@@ -421,6 +429,8 @@ Result GraphicsPipeline::CreateRenderPass() {
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment_desc.back().finalLayout =
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attachment_desc.back().samples =
+ static_cast<VkSampleCountFlagBits>(info->buffer->GetSamples());
VkAttachmentReference ref = VkAttachmentReference();
ref.attachment = static_cast<uint32_t>(attachment_desc.size() - 1);
@@ -446,6 +456,23 @@ Result GraphicsPipeline::CreateRenderPass() {
subpass_desc.pDepthStencilAttachment = &depth_refer;
}
+ for (const auto* info : resolve_targets_) {
+ attachment_desc.push_back(kDefaultAttachmentDesc);
+ attachment_desc.back().format =
+ device_->GetVkFormat(*info->buffer->GetFormat());
+ attachment_desc.back().initialLayout =
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attachment_desc.back().finalLayout =
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference ref = VkAttachmentReference();
+ ref.attachment = static_cast<uint32_t>(attachment_desc.size() - 1);
+ ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ resolve_refer.push_back(ref);
+ }
+
+ subpass_desc.pResolveAttachments = resolve_refer.data();
+
VkRenderPassCreateInfo render_pass_info = VkRenderPassCreateInfo();
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
render_pass_info.attachmentCount =
@@ -621,6 +648,16 @@ Result GraphicsPipeline::CreateVkGraphicsPipeline(
VK_FALSE, /* alphaToOneEnable */
};
+ // Search for multisampled color buffers and adjust the rasterization samples
+ // to match.
+ for (const auto& cb : color_buffers_) {
+ uint32_t samples = cb->buffer->GetSamples();
+ assert(static_cast<VkSampleCountFlagBits>(samples) >=
+ multisampleInfo.rasterizationSamples);
+ multisampleInfo.rasterizationSamples =
+ static_cast<VkSampleCountFlagBits>(samples);
+ }
+
VkGraphicsPipelineCreateInfo pipeline_info = VkGraphicsPipelineCreateInfo();
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_info.stageCount = static_cast<uint32_t>(shader_stage_info.size());
@@ -704,8 +741,9 @@ Result GraphicsPipeline::Initialize(uint32_t width,
if (!r.IsSuccess())
return r;
- frame_ = MakeUnique<FrameBuffer>(device_, color_buffers_,
- depth_stencil_buffer_, width, height);
+ frame_ =
+ MakeUnique<FrameBuffer>(device_, color_buffers_, depth_stencil_buffer_,
+ resolve_targets_, width, height);
r = frame_->Initialize(render_pass_);
if (!r.IsSuccess())
return r;
diff --git a/src/vulkan/graphics_pipeline.h b/src/vulkan/graphics_pipeline.h
index 7076231..cd55aad 100644
--- a/src/vulkan/graphics_pipeline.h
+++ b/src/vulkan/graphics_pipeline.h
@@ -43,6 +43,7 @@ class GraphicsPipeline : public Pipeline {
Device* device,
const std::vector<amber::Pipeline::BufferInfo>& color_buffers,
amber::Pipeline::BufferInfo depth_stencil_buffer,
+ const std::vector<amber::Pipeline::BufferInfo>& resolve_targets,
uint32_t fence_timeout_ms,
const std::vector<VkPipelineShaderStageCreateInfo>&);
~GraphicsPipeline() override;
@@ -86,8 +87,9 @@ class GraphicsPipeline : public Pipeline {
VkRenderPass render_pass_ = VK_NULL_HANDLE;
std::unique_ptr<FrameBuffer> frame_;
- // color buffers are owned by the amber::Pipeline.
+ // color buffers and resolve targets are owned by the amber::Pipeline.
std::vector<const amber::Pipeline::BufferInfo*> color_buffers_;
+ std::vector<const amber::Pipeline::BufferInfo*> resolve_targets_;
amber::Pipeline::BufferInfo depth_stencil_buffer_;
std::unique_ptr<IndexBuffer> index_buffer_;
diff --git a/src/vulkan/image_descriptor.cc b/src/vulkan/image_descriptor.cc
index 94e67d0..1d20244 100644
--- a/src/vulkan/image_descriptor.cc
+++ b/src/vulkan/image_descriptor.cc
@@ -29,51 +29,25 @@ ImageDescriptor::ImageDescriptor(Buffer* buffer,
Device* device,
uint32_t base_mip_level,
uint32_t desc_set,
- uint32_t binding)
- : BufferBackedDescriptor(buffer, type, device, desc_set, binding),
+ uint32_t binding,
+ Pipeline* pipeline)
+ : BufferBackedDescriptor(buffer, type, device, desc_set, binding, pipeline),
base_mip_level_(base_mip_level),
vulkan_sampler_(device) {}
ImageDescriptor::~ImageDescriptor() = default;
-Result ImageDescriptor::RecordCopyDataToResourceIfNeeded(
- CommandBuffer* command) {
- const auto transfer_images = GetResources();
- for (const auto& image : transfer_images) {
- // Static cast is safe, because the type is known to be TransferImage*.
- static_cast<TransferImage*>(image.second)
- ->ImageBarrier(command, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT);
- }
-
- Result r = BufferBackedDescriptor::RecordCopyDataToResourceIfNeeded(command);
- if (!r.IsSuccess())
- return r;
-
- // Just do this as early as possible.
- for (const auto& image : transfer_images) {
- static_cast<TransferImage*>(image.second)
- ->ImageBarrier(command, VK_IMAGE_LAYOUT_GENERAL,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
- }
-
- return {};
-}
-
Result ImageDescriptor::CreateResourceIfNeeded() {
- if (!transfer_images_.empty()) {
- return Result(
- "Vulkan: ImageDescriptor::CreateResourceIfNeeded() must be called "
- "only when |transfer_images| is empty");
- }
+ auto& transfer_resources = pipeline_->GetDescriptorTransferResources();
for (const auto& amber_buffer : GetAmberBuffers()) {
if (amber_buffer->ValuePtr()->empty())
continue;
// Check if the transfer image is already created.
- if (transfer_images_.count(amber_buffer) > 0)
+ if (transfer_resources.count(amber_buffer) > 0) {
continue;
+ }
// Default to 2D image.
VkImageType image_type = VK_IMAGE_TYPE_2D;
@@ -103,14 +77,8 @@ Result ImageDescriptor::CreateResourceIfNeeded() {
aspect = VK_IMAGE_ASPECT_COLOR_BIT;
}
- auto transfer_image = MakeUnique<TransferImage>(
- device_, *fmt, aspect, image_type, amber_buffer->GetWidth(),
- amber_buffer->GetHeight(), amber_buffer->GetDepth(),
- amber_buffer->GetMipLevels(), base_mip_level_, VK_REMAINING_MIP_LEVELS,
- amber_buffer->GetSamples());
VkImageUsageFlags usage =
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-
if (type_ == DescriptorType::kStorageImage) {
usage |= VK_IMAGE_USAGE_STORAGE_BIT;
} else {
@@ -119,11 +87,14 @@ Result ImageDescriptor::CreateResourceIfNeeded() {
usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
- Result r = transfer_image->Initialize(usage);
- if (!r.IsSuccess())
- return r;
+ auto transfer_image = MakeUnique<TransferImage>(
+ device_, *fmt, aspect, image_type, usage, amber_buffer->GetWidth(),
+ amber_buffer->GetHeight(), amber_buffer->GetDepth(),
+ amber_buffer->GetMipLevels(), base_mip_level_, VK_REMAINING_MIP_LEVELS,
+ amber_buffer->GetSamples());
- transfer_images_[amber_buffer] = std::move(transfer_image);
+ // Store the transfer image to the pipeline's map of transfer images.
+ transfer_resources[amber_buffer] = std::move(transfer_image);
}
if (amber_sampler_) {
@@ -136,28 +107,6 @@ Result ImageDescriptor::CreateResourceIfNeeded() {
return {};
}
-Result ImageDescriptor::RecordCopyDataToHost(CommandBuffer* command) {
- if (!IsReadOnly()) {
- for (auto& image : GetResources()) {
- static_cast<TransferImage*>(image.second)
- ->ImageBarrier(command, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT);
- }
-
- BufferBackedDescriptor::RecordCopyDataToHost(command);
- }
-
- return {};
-}
-
-Result ImageDescriptor::MoveResourceToBufferOutput() {
- Result r = BufferBackedDescriptor::MoveResourceToBufferOutput();
-
- transfer_images_.clear();
-
- return r;
-}
-
void ImageDescriptor::UpdateDescriptorSetIfNeeded(
VkDescriptorSet descriptor_set) {
if (!is_descriptor_set_update_needed_)
@@ -170,7 +119,9 @@ void ImageDescriptor::UpdateDescriptorSetIfNeeded(
// Create VkDescriptorImageInfo for every descriptor image.
for (const auto& amber_buffer : GetAmberBuffers()) {
- const auto& image = transfer_images_[amber_buffer];
+ const auto& image =
+ pipeline_->GetDescriptorTransferResources()[amber_buffer]
+ ->AsTransferImage();
VkDescriptorImageInfo image_info = {vulkan_sampler_.GetVkSampler(),
image->GetVkImageView(), layout};
image_infos.push_back(image_info);
@@ -191,23 +142,5 @@ void ImageDescriptor::UpdateDescriptorSetIfNeeded(
is_descriptor_set_update_needed_ = false;
}
-std::vector<std::pair<Buffer*, Resource*>> ImageDescriptor::GetResources() {
- std::vector<std::pair<Buffer*, Resource*>> ret;
- // Add unique amber buffers and related transfer images to the vector.
- for (const auto& amber_buffer : GetAmberBuffers()) {
- // Skip duplicate values.
- const auto& image =
- std::find_if(ret.begin(), ret.end(),
- [&](const std::pair<Buffer*, Resource*>& buffer) {
- return buffer.first == amber_buffer;
- });
- if (image != ret.end())
- continue;
-
- ret.emplace_back(amber_buffer, transfer_images_[amber_buffer].get());
- }
- return ret;
-}
-
} // namespace vulkan
} // namespace amber
diff --git a/src/vulkan/image_descriptor.h b/src/vulkan/image_descriptor.h
index 908ed17..3046436 100644
--- a/src/vulkan/image_descriptor.h
+++ b/src/vulkan/image_descriptor.h
@@ -21,6 +21,7 @@
#include <vector>
#include "src/vulkan/buffer_backed_descriptor.h"
+#include "src/vulkan/pipeline.h"
#include "src/vulkan/sampler.h"
#include "src/vulkan/transfer_image.h"
@@ -34,22 +35,18 @@ class ImageDescriptor : public BufferBackedDescriptor {
Device* device,
uint32_t base_mip_level,
uint32_t desc_set,
- uint32_t binding);
+ uint32_t binding,
+ Pipeline* pipeline);
~ImageDescriptor() override;
void UpdateDescriptorSetIfNeeded(VkDescriptorSet descriptor_set) override;
- Result RecordCopyDataToResourceIfNeeded(CommandBuffer* command) override;
Result CreateResourceIfNeeded() override;
- Result RecordCopyDataToHost(CommandBuffer* command) override;
- Result MoveResourceToBufferOutput() override;
void SetAmberSampler(amber::Sampler* sampler) { amber_sampler_ = sampler; }
- protected:
- std::vector<std::pair<Buffer*, Resource*>> GetResources() override;
+ ImageDescriptor* AsImageDescriptor() override { return this; }
private:
uint32_t base_mip_level_ = 0;
- std::unordered_map<Buffer*, std::unique_ptr<TransferImage>> transfer_images_;
amber::Sampler* amber_sampler_ = nullptr;
amber::vulkan::Sampler vulkan_sampler_;
};
diff --git a/src/vulkan/index_buffer.cc b/src/vulkan/index_buffer.cc
index 73a9083..b651427 100644
--- a/src/vulkan/index_buffer.cc
+++ b/src/vulkan/index_buffer.cc
@@ -38,8 +38,12 @@ Result IndexBuffer::SendIndexData(CommandBuffer* command, Buffer* buffer) {
transfer_buffer_ =
MakeUnique<TransferBuffer>(device_, buffer->GetSizeInBytes(), nullptr);
- Result r = transfer_buffer_->Initialize(VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
- VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ Result r = transfer_buffer_->AddUsageFlags(VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ if (!r.IsSuccess())
+ return r;
+
+ r = transfer_buffer_->Initialize();
if (!r.IsSuccess())
return r;
diff --git a/src/vulkan/pipeline.cc b/src/vulkan/pipeline.cc
index 259f375..df301e4 100644
--- a/src/vulkan/pipeline.cc
+++ b/src/vulkan/pipeline.cc
@@ -273,6 +273,18 @@ Result Pipeline::GetDescriptorSlot(uint32_t desc_set,
return {};
}
+Result Pipeline::AddDescriptorBuffer(Buffer* amber_buffer) {
+ // Don't add the buffer if it's already added.
+ const auto& buffer = std::find_if(
+ descriptor_buffers_.begin(), descriptor_buffers_.end(),
+ [&](const Buffer* buf) { return buf == amber_buffer; });
+ if (buffer != descriptor_buffers_.end()) {
+ return {};
+ }
+ descriptor_buffers_.push_back(amber_buffer);
+ return {};
+}
+
Result Pipeline::AddBufferDescriptor(const BufferCommand* cmd) {
if (cmd == nullptr)
return Result("Pipeline::AddBufferDescriptor BufferCommand is nullptr");
@@ -319,7 +331,7 @@ Result Pipeline::AddBufferDescriptor(const BufferCommand* cmd) {
if (is_image) {
auto image_desc = MakeUnique<ImageDescriptor>(
cmd->GetBuffer(), desc_type, device_, cmd->GetBaseMipLevel(),
- cmd->GetDescriptorSet(), cmd->GetBinding());
+ cmd->GetDescriptorSet(), cmd->GetBinding(), this);
if (cmd->IsCombinedImageSampler())
image_desc->SetAmberSampler(cmd->GetSampler());
@@ -327,9 +339,10 @@ Result Pipeline::AddBufferDescriptor(const BufferCommand* cmd) {
} else {
auto buffer_desc = MakeUnique<BufferDescriptor>(
cmd->GetBuffer(), desc_type, device_, cmd->GetDescriptorSet(),
- cmd->GetBinding());
+ cmd->GetBinding(), this);
descriptors.push_back(std::move(buffer_desc));
}
+ AddDescriptorBuffer(cmd->GetBuffer());
desc = descriptors.back().get();
} else {
if (desc->GetDescriptorType() != desc_type) {
@@ -338,6 +351,7 @@ Result Pipeline::AddBufferDescriptor(const BufferCommand* cmd) {
"descriptor types");
}
desc->AsBufferBackedDescriptor()->AddAmberBuffer(cmd->GetBuffer());
+ AddDescriptorBuffer(cmd->GetBuffer());
}
if (cmd->IsUniformDynamic() || cmd->IsSSBODynamic())
@@ -409,6 +423,16 @@ Result Pipeline::SendDescriptorDataToDeviceIfNeeded() {
}
}
+ // Initialize transfer buffers / images.
+ for (auto buffer : descriptor_buffers_) {
+ if (descriptor_transfer_resources_.count(buffer) == 0) {
+ return Result(
+ "Vulkan: Pipeline::SendDescriptorDataToDeviceIfNeeded() "
+ "descriptor's transfer resource is not found");
+ }
+ descriptor_transfer_resources_[buffer]->Initialize();
+ }
+
// Note that if a buffer for a descriptor is host accessible and
// does not need to record a command to copy data to device, it
// directly writes data to the buffer. The direct write must be
@@ -424,11 +448,27 @@ Result Pipeline::SendDescriptorDataToDeviceIfNeeded() {
if (!guard.IsRecording())
return guard.GetResult();
- for (auto& info : descriptor_set_info_) {
- for (auto& desc : info.descriptors) {
- Result r = desc->RecordCopyDataToResourceIfNeeded(command_.get());
- if (!r.IsSuccess())
- return r;
+ // Copy descriptor data to transfer resources.
+ for (auto& buffer : descriptor_buffers_) {
+ if (auto transfer_buffer =
+ descriptor_transfer_resources_[buffer]->AsTransferBuffer()) {
+ BufferBackedDescriptor::RecordCopyBufferDataToTransferResourceIfNeeded(
+ GetCommandBuffer(), buffer, transfer_buffer);
+ } else if (auto transfer_image =
+ descriptor_transfer_resources_[buffer]->AsTransferImage()) {
+ transfer_image->ImageBarrier(GetCommandBuffer(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ BufferBackedDescriptor::RecordCopyBufferDataToTransferResourceIfNeeded(
+ GetCommandBuffer(), buffer, transfer_image);
+
+ transfer_image->ImageBarrier(GetCommandBuffer(), VK_IMAGE_LAYOUT_GENERAL,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
+ } else {
+ return Result(
+ "Vulkan: Pipeline::SendDescriptorDataToDeviceIfNeeded() "
+ "this should be unreachable");
}
}
return guard.Submit(GetFenceTimeout());
@@ -472,14 +512,38 @@ void Pipeline::BindVkDescriptorSets(const VkPipelineLayout& pipeline_layout) {
}
Result Pipeline::ReadbackDescriptorsToHostDataQueue() {
+ // Record required commands to copy the data to a host visible buffer.
{
CommandBufferGuard guard(GetCommandBuffer());
if (!guard.IsRecording())
return guard.GetResult();
- for (auto& desc_set : descriptor_set_info_) {
- for (auto& desc : desc_set.descriptors)
- desc->RecordCopyDataToHost(command_.get());
+ for (auto& buffer : descriptor_buffers_) {
+ if (descriptor_transfer_resources_.count(buffer) == 0) {
+ return Result(
+ "Vulkan: Pipeline::ReadbackDescriptorsToHostDataQueue() "
+ "descriptor's transfer resource is not found");
+ }
+ if (auto transfer_buffer =
+ descriptor_transfer_resources_[buffer]->AsTransferBuffer()) {
+ Result r = BufferBackedDescriptor::RecordCopyTransferResourceToHost(
+ GetCommandBuffer(), transfer_buffer);
+ if (!r.IsSuccess())
+ return r;
+ } else if (auto transfer_image = descriptor_transfer_resources_[buffer]
+ ->AsTransferImage()) {
+ transfer_image->ImageBarrier(GetCommandBuffer(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+ Result r = BufferBackedDescriptor::RecordCopyTransferResourceToHost(
+ GetCommandBuffer(), transfer_image);
+ if (!r.IsSuccess())
+ return r;
+ } else {
+ return Result(
+ "Vulkan: Pipeline::ReadbackDescriptorsToHostDataQueue() "
+ "this should be unreachable");
+ }
}
Result r = guard.Submit(GetFenceTimeout());
@@ -487,14 +551,15 @@ Result Pipeline::ReadbackDescriptorsToHostDataQueue() {
return r;
}
- for (auto& desc_set : descriptor_set_info_) {
- for (auto& desc : desc_set.descriptors) {
- Result r = desc->MoveResourceToBufferOutput();
- if (!r.IsSuccess())
- return r;
- }
+ // Move data from transfer buffers to output buffers.
+ for (auto& buffer : descriptor_buffers_) {
+ auto& transfer_resource = descriptor_transfer_resources_[buffer];
+ Result r = BufferBackedDescriptor::MoveTransferResourceToBufferOutput(
+ transfer_resource.get(), buffer);
+ if (!r.IsSuccess())
+ return r;
}
-
+ descriptor_transfer_resources_.clear();
return {};
}
diff --git a/src/vulkan/pipeline.h b/src/vulkan/pipeline.h
index 98b0c2a..1f85cb6 100644
--- a/src/vulkan/pipeline.h
+++ b/src/vulkan/pipeline.h
@@ -27,6 +27,7 @@
#include "src/vulkan/buffer_backed_descriptor.h"
#include "src/vulkan/command_buffer.h"
#include "src/vulkan/push_constant.h"
+#include "src/vulkan/resource.h"
namespace amber {
@@ -59,6 +60,11 @@ class Pipeline {
/// buffer data object and put it into buffer data queue in host.
Result ReadbackDescriptorsToHostDataQueue();
+ std::unordered_map<Buffer*, std::unique_ptr<Resource>>&
+ GetDescriptorTransferResources() {
+ return descriptor_transfer_resources_;
+ }
+
void SetEntryPointName(VkShaderStageFlagBits stage,
const std::string& entry) {
entry_points_[stage] = entry;
@@ -115,10 +121,17 @@ class Pipeline {
Result CreateDescriptorSetLayouts();
Result CreateDescriptorPools();
Result CreateDescriptorSets();
+ /// Adds a buffer used by a descriptor. The added buffers are be stored in
+ /// |descriptor_buffers_| vector in the order they are added.
+ Result AddDescriptorBuffer(Buffer* amber_buffer);
PipelineType pipeline_type_;
std::vector<DescriptorSetInfo> descriptor_set_info_;
std::vector<VkPipelineShaderStageCreateInfo> shader_stage_info_;
+ std::unordered_map<Buffer*, std::unique_ptr<Resource>>
+ descriptor_transfer_resources_;
+ /// Buffers used by descriptors (buffer descriptors and image descriptors).
+ std::vector<Buffer*> descriptor_buffers_;
uint32_t fence_timeout_ms_ = 1000;
bool descriptor_related_objects_already_created_ = false;
diff --git a/src/vulkan/resource.h b/src/vulkan/resource.h
index 1ed447a..d3cc0de 100644
--- a/src/vulkan/resource.h
+++ b/src/vulkan/resource.h
@@ -27,9 +27,10 @@ namespace vulkan {
class CommandBuffer;
class Device;
+class TransferBuffer;
+class TransferImage;
-// Class for Vulkan resources. Its children are Vulkan Buffer, Vulkan Image,
-// and a class for push constant.
+// Class for Vulkan resources. Its children are Vulkan Buffer and Vulkan Image.
class Resource {
public:
virtual ~Resource();
@@ -46,6 +47,12 @@ class Resource {
uint32_t GetSizeInBytes() const { return size_in_bytes_; }
void UpdateMemoryWithRawData(const std::vector<uint8_t>& raw_data);
+ bool IsReadOnly() const { return is_read_only_; }
+ void SetReadOnly(bool read_only) { is_read_only_ = read_only; }
+ virtual Result Initialize() = 0;
+ virtual TransferBuffer* AsTransferBuffer() { return nullptr; }
+ virtual TransferImage* AsTransferImage() { return nullptr; }
+
protected:
Resource(Device* device, uint32_t size);
Result CreateVkBuffer(VkBuffer* buffer, VkBufferUsageFlags usage);
@@ -82,6 +89,7 @@ class Resource {
private:
uint32_t size_in_bytes_ = 0;
void* memory_ptr_ = nullptr;
+ bool is_read_only_ = false;
};
} // namespace vulkan
diff --git a/src/vulkan/transfer_buffer.cc b/src/vulkan/transfer_buffer.cc
index a13b22e..512fb7b 100644
--- a/src/vulkan/transfer_buffer.cc
+++ b/src/vulkan/transfer_buffer.cc
@@ -44,8 +44,14 @@ TransferBuffer::~TransferBuffer() {
}
}
-Result TransferBuffer::Initialize(const VkBufferUsageFlags usage) {
- Result r = CreateVkBuffer(&buffer_, usage);
+Result TransferBuffer::Initialize() {
+ if (buffer_) {
+ return Result(
+ "Vulkan: TransferBuffer::Initialize() transfer buffer already "
+ "initialized.");
+ }
+
+ Result r = CreateVkBuffer(&buffer_, usage_flags_);
if (!r.IsSuccess())
return r;
@@ -58,8 +64,8 @@ Result TransferBuffer::Initialize(const VkBufferUsageFlags usage) {
return r;
// Create buffer view
- if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
- VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
+ if (usage_flags_ & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
+ VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
VkBufferViewCreateInfo buffer_view_info = VkBufferViewCreateInfo();
buffer_view_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
buffer_view_info.buffer = buffer_;
diff --git a/src/vulkan/transfer_buffer.h b/src/vulkan/transfer_buffer.h
index 2c0a51d..7d96bec 100644
--- a/src/vulkan/transfer_buffer.h
+++ b/src/vulkan/transfer_buffer.h
@@ -34,7 +34,17 @@ class TransferBuffer : public Resource {
TransferBuffer(Device* device, uint32_t size_in_bytes, Format* format);
~TransferBuffer() override;
- Result Initialize(const VkBufferUsageFlags usage);
+ TransferBuffer* AsTransferBuffer() override { return this; }
+ Result AddUsageFlags(VkBufferUsageFlags flags) {
+ if (buffer_ != VK_NULL_HANDLE) {
+ return Result(
+ "Vulkan: TransferBuffer::AddUsageFlags Usage flags can't be changed "
+ "after initializing the buffer.");
+ }
+ usage_flags_ |= flags;
+ return {};
+ }
+ Result Initialize() override;
const VkBufferView* GetVkBufferView() const { return &view_; }
VkBuffer GetVkBuffer() const { return buffer_; }
@@ -47,6 +57,7 @@ class TransferBuffer : public Resource {
void CopyToHost(CommandBuffer* command_buffer) override;
private:
+ VkBufferUsageFlags usage_flags_ = 0;
VkBuffer buffer_ = VK_NULL_HANDLE;
VkDeviceMemory memory_ = VK_NULL_HANDLE;
VkBufferView view_ = VK_NULL_HANDLE;
diff --git a/src/vulkan/transfer_image.cc b/src/vulkan/transfer_image.cc
index 545549d..adfae62 100644
--- a/src/vulkan/transfer_image.cc
+++ b/src/vulkan/transfer_image.cc
@@ -70,6 +70,7 @@ TransferImage::TransferImage(Device* device,
const Format& format,
VkImageAspectFlags aspect,
VkImageType image_type,
+ VkImageUsageFlags image_usage_flags,
uint32_t x,
uint32_t y,
uint32_t z,
@@ -96,6 +97,7 @@ TransferImage::TransferImage(Device* device,
image_info_.extent = {x, y, z};
image_info_.mipLevels = mip_levels;
image_info_.samples = GetVkSampleCount(samples);
+ image_info_.usage = image_usage_flags;
}
TransferImage::~TransferImage() {
@@ -122,12 +124,10 @@ TransferImage::~TransferImage() {
}
}
-Result TransferImage::Initialize(VkImageUsageFlags usage) {
+Result TransferImage::Initialize() {
if (image_ != VK_NULL_HANDLE)
return Result("Vulkan::TransferImage was already initialized");
- image_info_.usage = usage;
-
if (device_->GetPtrs()->vkCreateImage(device_->GetVkDevice(), &image_info_,
nullptr, &image_) != VK_SUCCESS) {
return Result("Vulkan::Calling vkCreateImage Fail");
@@ -141,7 +141,7 @@ Result TransferImage::Initialize(VkImageUsageFlags usage) {
return r;
if (aspect_ & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) &&
- !(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
+ !(image_info_.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
// Combined depth/stencil image used as a descriptor. Only one aspect can be
// used for the image view.
r = CreateVkImageView(VK_IMAGE_ASPECT_DEPTH_BIT);
diff --git a/src/vulkan/transfer_image.h b/src/vulkan/transfer_image.h
index 741ee3c..3af71d2 100644
--- a/src/vulkan/transfer_image.h
+++ b/src/vulkan/transfer_image.h
@@ -33,6 +33,7 @@ class TransferImage : public Resource {
const Format& format,
VkImageAspectFlags aspect,
VkImageType image_type,
+ VkImageUsageFlags image_usage_flags,
uint32_t x,
uint32_t y,
uint32_t z,
@@ -42,7 +43,8 @@ class TransferImage : public Resource {
uint32_t samples);
~TransferImage() override;
- Result Initialize(VkImageUsageFlags usage);
+ TransferImage* AsTransferImage() override { return this; }
+ Result Initialize() override;
VkImageView GetVkImageView() const { return view_; }
void ImageBarrier(CommandBuffer* command_buffer,
diff --git a/src/vulkan/vertex_buffer.cc b/src/vulkan/vertex_buffer.cc
index 7503681..557b0a3 100644
--- a/src/vulkan/vertex_buffer.cc
+++ b/src/vulkan/vertex_buffer.cc
@@ -85,8 +85,11 @@ Result VertexBuffer::SendVertexData(CommandBuffer* command) {
uint32_t bytes = buf->GetSizeInBytes();
transfer_buffers_.push_back(
MakeUnique<TransferBuffer>(device_, bytes, nullptr));
- Result r = transfer_buffers_.back()->Initialize(
+ Result r = transfer_buffers_.back()->AddUsageFlags(
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ if (!r.IsSuccess())
+ return r;
+ r = transfer_buffers_.back()->Initialize();
std::memcpy(transfer_buffers_.back()->HostAccessibleMemoryPtr(),
buf->GetValues<void>(), bytes);
diff --git a/tests/cases/compute_one_buffer_in_multiple_bindings.amber b/tests/cases/compute_one_buffer_in_multiple_bindings.amber
new file mode 100644
index 0000000..d16bda5
--- /dev/null
+++ b/tests/cases/compute_one_buffer_in_multiple_bindings.amber
@@ -0,0 +1,94 @@
+#!amber
+# Copyright 2021 The Amber 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.
+
+SHADER compute compute_shader GLSL
+#version 430
+
+layout(set = 0, binding = 0) uniform uniform_0 {
+ vec4 uniform_data_0;
+};
+layout(set = 0, binding = 1) buffer block_0 {
+ vec4 storage_data_0;
+};
+
+layout(set = 1, binding = 0) uniform uniform_1 {
+ vec4 uniform_data_1;
+};
+layout(set = 1, binding = 1) buffer block_1 {
+ vec4 storage_data_1;
+};
+
+uniform layout(set = 2, binding = 0, rgba32f) imageBuffer texelBuffer;
+uniform layout(set = 2, binding = 1) samplerBuffer texelsIn;
+
+void main() {
+ // Verify that the uniform and storage buffers have the same contents and multiply by 2 if true)
+ if (uniform_data_0 == storage_data_0) {
+ storage_data_0 = storage_data_0 * 2;
+ }
+ if (uniform_data_1 == storage_data_1) {
+ storage_data_1 = storage_data_1 * 2;
+ }
+
+ // Load values from index 1 using storage texel buffer.
+ vec4 texel = imageLoad(texelBuffer, 1);
+
+ // Load values from index 2 using uniform texel buffer.
+ vec4 color = texelFetch(texelsIn, 2);
+
+ // Store values to index 3.
+ imageStore(texelBuffer, 3, texel + color);
+}
+END
+
+# The Vulkan spec lists the maximum value of minStorageBufferOffsetAlignment
+# (i.e. the maximum possible alignment requirement) as 256 bytes.
+# Meaningful data is placed at this offset.
+BUFFER buf0 DATA_TYPE R32G32B32A32_SFLOAT DATA
+1.0 2.0 3.0 4.0
+0.1 0.2 0.3 0.4
+0.5 0.6 0.7 0.8
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+0.0 0.0 0.0 0.0
+5.0 6.0 7.0 8.0
+END
+
+PIPELINE compute pipeline
+ ATTACH compute_shader
+
+ BIND BUFFER buf0 AS uniform DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER buf0 AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER buf0 AS uniform DESCRIPTOR_SET 1 BINDING 0 DESCRIPTOR_OFFSET 256
+ BIND BUFFER buf0 AS storage DESCRIPTOR_SET 1 BINDING 1 DESCRIPTOR_OFFSET 256
+ BIND BUFFER buf0 AS storage_texel_buffer DESCRIPTOR_SET 2 BINDING 0
+ BIND BUFFER buf0 AS uniform_texel_buffer DESCRIPTOR_SET 2 BINDING 1
+END
+
+RUN pipeline 1 1 1
+
+EXPECT buf0 IDX 0 EQ 2.0 4.0 6.0 8.0 # Values written to the first storage buffer binding
+EXPECT buf0 IDX 48 EQ 0.6 0.8 1.0 1.2 # Values written to the storage texel buffer binding
+EXPECT buf0 IDX 256 EQ 10.0 12.0 14.0 16.0 # Values written to the second storage buffer binding
diff --git a/tests/cases/debugger_hlsl_basic_compute.amber b/tests/cases/debugger_hlsl_basic_compute.amber
index 84db5df..f1572b3 100644
--- a/tests/cases/debugger_hlsl_basic_compute.amber
+++ b/tests/cases/debugger_hlsl_basic_compute.amber
@@ -18,7 +18,7 @@ SET ENGINE_DATA fence_timeout_ms 1000000
VIRTUAL_FILE "compute.hlsl"
[[vk::binding(0)]]
-StructuredBuffer<int> data;
+RWStructuredBuffer<int> data;
[numthreads(1,1,1)]
void main() {
diff --git a/tests/cases/debugger_hlsl_basic_vertex.amber b/tests/cases/debugger_hlsl_basic_vertex.amber
index 86d0381..79ea512 100644
--- a/tests/cases/debugger_hlsl_basic_vertex.amber
+++ b/tests/cases/debugger_hlsl_basic_vertex.amber
@@ -106,6 +106,12 @@ CLEAR pipeline
DEBUG pipeline DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6
THREAD VERTEX_INDEX 0
+ EXPECT LOCATION "vs.hlsl" 6 "VS_OUTPUT main(float4 pos : POSITION,"
+ STEP_IN
+ EXPECT LOCATION "vs.hlsl" 7 " float4 color : COLOR) {"
+ STEP_IN
+ EXPECT LOCATION "vs.hlsl" 8 " VS_OUTPUT vout;"
+ STEP_IN
EXPECT LOCATION "vs.hlsl" 9 " vout.pos = pos;"
EXPECT LOCAL "pos.x" EQ -1.000000
EXPECT LOCAL "pos.y" EQ -1.000000
diff --git a/tests/cases/debugger_hlsl_function_call.amber b/tests/cases/debugger_hlsl_function_call.amber
index 9504b03..3542b15 100644
--- a/tests/cases/debugger_hlsl_function_call.amber
+++ b/tests/cases/debugger_hlsl_function_call.amber
@@ -18,7 +18,7 @@ SET ENGINE_DATA fence_timeout_ms 1000000
VIRTUAL_FILE "compute.hlsl"
[[vk::binding(0)]]
-StructuredBuffer<int> data;
+RWStructuredBuffer<int> data;
int C(int x)
{
diff --git a/tests/cases/debugger_hlsl_shadowed_vars.amber b/tests/cases/debugger_hlsl_shadowed_vars.amber
index bf8a790..d1f75a5 100644
--- a/tests/cases/debugger_hlsl_shadowed_vars.amber
+++ b/tests/cases/debugger_hlsl_shadowed_vars.amber
@@ -99,7 +99,8 @@ BUFFER framebuffer FORMAT B8G8R8A8_UNORM
PIPELINE graphics pipeline
ATTACH vtex_shader
SHADER_OPTIMIZATION vtex_shader
- --legalize-hlsl
+ --inline-entry-points-exhaustive
+ --eliminate-dead-functions
END
ATTACH frag_shader
@@ -117,6 +118,10 @@ CLEAR pipeline
DEBUG pipeline DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6
THREAD VERTEX_INDEX 0
+ EXPECT LOCATION "vs.hlsl" 5 "VS_OUTPUT main(float4 pos : POSITION,"
+ STEP_IN
+ EXPECT LOCATION "vs.hlsl" 6 " float4 color : COLOR) {"
+ STEP_IN
EXPECT LOCATION "vs.hlsl" 7 " float a = 1.0;"
STEP_IN
EXPECT LOCATION "vs.hlsl" 8 " float b = 2.0;"
diff --git a/tests/cases/debugger_spirv_line_stepping.amber b/tests/cases/debugger_spirv_line_stepping.amber
index 1d3e33b..478e4fd 100644
--- a/tests/cases/debugger_spirv_line_stepping.amber
+++ b/tests/cases/debugger_spirv_line_stepping.amber
@@ -94,10 +94,16 @@ DEBUG pipeline 1 1 1
END
EXPECT LOCATION "ComputeShader0.spvasm" 20 "%5 = OpVariable %11 Uniform"
STEP_IN
+ EXPECT LOCATION "ComputeShader0.spvasm" 21 "%12 = OpConstant %9 0"
+ STEP_IN
+ EXPECT LOCATION "ComputeShader0.spvasm" 22 "%13 = OpConstant %10 0"
+ STEP_IN
EXPECT LOCATION "ComputeShader0.spvasm" 25 "%2 = OpVariable %15 Input"
STEP_IN
EXPECT LOCATION "ComputeShader0.spvasm" 27 "%6 = OpVariable %11 Uniform"
STEP_IN
+ EXPECT LOCATION "ComputeShader0.spvasm" 29 "%1 = OpFunction %7 None %8"
+ STEP_IN
EXPECT LOCATION "ComputeShader0.spvasm" 31 "%19 = OpAccessChain %16 %2 %13"
STEP_IN
EXPECT LOCATION "ComputeShader0.spvasm" 32 "%20 = OpLoad %10 %19"
diff --git a/tests/cases/draw_rect_blend.amber b/tests/cases/draw_rect_blend.amber
new file mode 100644
index 0000000..c47b93f
--- /dev/null
+++ b/tests/cases/draw_rect_blend.amber
@@ -0,0 +1,46 @@
+#!amber
+# Copyright 2021 The Amber 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.
+
+SHADER vertex vert_shader PASSTHROUGH
+SHADER fragment frag_shader GLSL
+#version 430
+layout(location = 0) out vec4 color_out;
+void main()
+{
+ color_out = vec4(1.0, 0.0, 0.0, 0.5);
+}
+END
+
+BUFFER framebuffer FORMAT B8G8R8A8_UNORM
+
+PIPELINE graphics pipeline
+ ATTACH vert_shader
+ ATTACH frag_shader
+ BIND BUFFER framebuffer AS color LOCATION 0
+
+ BLEND
+ SRC_COLOR_FACTOR src_alpha
+ DST_COLOR_FACTOR one_minus_src_alpha
+ COLOR_OP add
+ SRC_ALPHA_FACTOR one
+ DST_ALPHA_FACTOR one
+ ALPHA_OP max
+ END
+END
+
+CLEAR_COLOR pipeline 0 255 0 255
+CLEAR pipeline
+RUN pipeline DRAW_RECT POS 0 0 SIZE 250 250
+EXPECT framebuffer IDX 0 0 SIZE 250 250 EQ_RGBA 128 128 0 255 TOLERANCE 5%
diff --git a/tests/cases/float16.amber b/tests/cases/float16.amber
index 88baf13..0a8fd04 100644
--- a/tests/cases/float16.amber
+++ b/tests/cases/float16.amber
@@ -13,9 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-INSTANCE_EXTENSION VK_KHR_get_physical_device_properties2
DEVICE_EXTENSION VK_KHR_shader_float16_int8
+DEVICE_EXTENSION VK_KHR_16bit_storage
+DEVICE_EXTENSION VK_KHR_storage_buffer_storage_class
DEVICE_FEATURE Float16Int8Features.shaderFloat16
+DEVICE_FEATURE Storage16BitFeatures.storageBuffer16BitAccess
SHADER compute f16 GLSL
#version 450
diff --git a/tests/cases/multisample_resolve.amber b/tests/cases/multisample_resolve.amber
new file mode 100644
index 0000000..594f9bb
--- /dev/null
+++ b/tests/cases/multisample_resolve.amber
@@ -0,0 +1,50 @@
+#!amber
+# Copyright 2021 The Amber 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.
+
+DEVICE_FEATURE sampleRateShading
+
+SHADER vertex vert_shader PASSTHROUGH
+
+SHADER fragment frag_shader GLSL
+#version 440
+layout(location = 0) out vec4 color;
+
+void main (void)
+{
+ if (gl_SampleID == 0)
+ color = vec4(1, 0, 0, 1);
+ else if (gl_SampleID == 1)
+ color = vec4(0, 1, 0, 1);
+ else if (gl_SampleID == 2)
+ color = vec4(0, 0, 1, 1);
+ else
+ color = vec4(1, 1, 1, 1);
+}
+END
+
+IMAGE framebuffer_ms FORMAT R8G8B8A8_UNORM DIM_2D WIDTH 64 HEIGHT 64 SAMPLES 4
+IMAGE framebuffer FORMAT R8G8B8A8_UNORM DIM_2D WIDTH 64 HEIGHT 64
+
+PIPELINE graphics pipeline
+ ATTACH vert_shader
+ ATTACH frag_shader
+ FRAMEBUFFER_SIZE 64 64
+ BIND BUFFER framebuffer_ms AS color LOCATION 0
+ BIND BUFFER framebuffer AS resolve
+END
+
+RUN pipeline DRAW_RECT POS 0 0 SIZE 64 64
+
+EXPECT framebuffer IDX 0 0 SIZE 64 64 EQ_RGBA 128 128 128 255 TOLERANCE 5%
diff --git a/tests/cases/tessellation_isolines.amber b/tests/cases/tessellation_isolines.amber
new file mode 100644
index 0000000..dd3f298
--- /dev/null
+++ b/tests/cases/tessellation_isolines.amber
@@ -0,0 +1,130 @@
+#!amber
+# Copyright 2021 The Amber 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.
+
+DEVICE_FEATURE tessellationShader
+
+SHADER vertex vert GLSL
+#version 450
+
+layout (location = 0) in vec3 inPosition;
+
+void main(void)
+{
+ gl_Position = vec4(inPosition, 1.0);
+}
+END
+
+SHADER tessellation_control tesc GLSL
+#version 450
+
+layout (vertices = 4) out;
+
+void main(void)
+{
+ gl_TessLevelOuter[0] = 6.0;
+ gl_TessLevelOuter[1] = 2.0;
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+}
+END
+
+SHADER tessellation_evaluation tese GLSL
+#version 450
+
+layout (isolines, equal_spacing, cw) in;
+
+void main(void)
+{
+ vec4 p1 = mix(gl_in[0].gl_Position,
+ gl_in[1].gl_Position,
+ gl_TessCoord.x);
+
+ vec4 p2 = mix(gl_in[2].gl_Position,
+ gl_in[3].gl_Position,
+ gl_TessCoord.x);
+
+ gl_Position = mix(p1, p2, gl_TessCoord.y);
+}
+END
+
+SHADER fragment frag GLSL
+#version 450
+
+layout (location = 0) out vec4 outColor;
+
+void main(void)
+{
+ outColor = vec4(1, 0, 0, 1);
+}
+END
+
+SHADER compute comp_shader GLSL
+#version 450
+layout(local_size_x=10,local_size_y=10) in;
+uniform layout(set=0, binding=0, rgba8) image2D resultImage;
+
+layout(set = 0, binding = 1) buffer block0
+{
+ int counter;
+};
+
+void main()
+{
+ ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
+ vec4 color = imageLoad(resultImage, uv);
+ if(color.r > 0.0) atomicAdd(counter, 1);
+}
+END
+
+BUFFER vertexPosition DATA_TYPE vec3<float> DATA
+-1.0 -1.0 0.0
+ 1.0 -1.0 0.0
+-1.0 1.0 0.0
+ 1.0 1.0 0.0
+END
+
+BUFFER counter DATA_TYPE int32 DATA 0 END
+
+BUFFER framebuffer FORMAT B8G8R8A8_UNORM
+
+PIPELINE graphics pipeline
+ ATTACH vert
+ ATTACH tesc
+ ATTACH tese
+ ATTACH frag
+
+ PATCH_CONTROL_POINTS 4
+
+ FRAMEBUFFER_SIZE 100 100
+ VERTEX_DATA vertexPosition LOCATION 0
+ BIND BUFFER framebuffer AS color LOCATION 0
+END
+
+CLEAR_COLOR pipeline 0 0 0 255
+CLEAR pipeline
+
+RUN pipeline DRAW_ARRAY AS PATCH_LIST START_IDX 0 COUNT 4
+
+PIPELINE compute verify_pipeline
+ ATTACH comp_shader
+ BIND BUFFER framebuffer AS storage_image DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER counter AS storage DESCRIPTOR_SET 0 BINDING 1
+ FRAMEBUFFER_SIZE 100 100
+END
+
+# Count the number of red pixels as the line position might differ between implementations.
+RUN verify_pipeline 10 10 1
+
+EXPECT counter IDX 0 TOLERANCE 50 EQ 500
diff --git a/tests/run_tests.py b/tests/run_tests.py
index 1fb7eb6..6cd8fc3 100755
--- a/tests/run_tests.py
+++ b/tests/run_tests.py
@@ -96,6 +96,8 @@ SUPPRESSIONS_SWIFTSHADER = [
# Unsupported depth/stencil formats
"draw_rectangles_depth_test_d24s8.amber",
"draw_rectangles_depth_test_x8d24.amber",
+ # Tessellation not supported
+ "tessellation_isolines.amber",
]
OPENCL_CASES = [
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 4319556..4668223 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -52,19 +52,30 @@ endif()
if (${AMBER_USE_LOCAL_VULKAN})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/vulkan-headers)
- set(BUILD_TESTS FALSE)
-
- # The vulkan-loader CMake file assumes that directory exists if
- # Wayland support is to be built.
- if(NOT EXISTS ${WAYLAND_CLIENT_INCLUDE_DIR})
- message(STATUS "Amber: Disabling Wayland support in Vulkan-Loader")
- set(BUILD_WSI_WAYLAND_SUPPORT OFF CACHE BOOL "" FORCE)
+ # Skip adding the validation layers and the Vulkan loader on Android.
+ if (NOT ANDROID)
+
+ set(BUILD_TESTS FALSE)
+
+ # The vulkan-loader CMake file assumes that directory exists if
+ # Wayland support is to be built.
+ if(NOT EXISTS ${WAYLAND_CLIENT_INCLUDE_DIR})
+ message(STATUS "Amber: Disabling Wayland support in Vulkan-Loader")
+ set(BUILD_WSI_WAYLAND_SUPPORT OFF CACHE BOOL "" FORCE)
+ endif()
+ message(STATUS "Amber: Disabling X11 support in Vulkan-Loader")
+ set(BUILD_WSI_XLIB_SUPPORT OFF CACHE BOOL "" FORCE)
+
+ set(ROBIN_HOOD_HASHING_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/robin-hood-hashing" CACHE STRING "" FORCE)
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/robin-hood-hashing)
+ set(SPIRV_HEADERS_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/spirv-headers/include" CACHE STRING "" FORCE)
+
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/vulkan-loader)
+ if (MSVC)
+ option(BUILD_WERROR "Treat compiler warnings as errors" OFF)
+ endif()
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/vulkan-validationlayers)
endif()
- message(STATUS "Amber: Disabling X11 support in Vulkan-Loader")
- set(BUILD_WSI_XLIB_SUPPORT OFF CACHE BOOL "" FORCE)
-
- add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/vulkan-loader)
- add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/vulkan-validationlayers)
endif()
if (${AMBER_ENABLE_VK_DEBUGGING})
@@ -152,6 +163,8 @@ if (${AMBER_ENABLE_CLSPV})
set(AMBER_CLSPV_LLVM_DIR "${CMAKE_CURRENT_SOURCE_DIR}/clspv-llvm")
endif()
+ list(APPEND CMAKE_MODULE_PATH ${AMBER_CLSPV_LLVM_DIR}/llvm/cmake/modules/)
+
set(CLSPV_LLVM_SOURCE_DIR "${AMBER_CLSPV_LLVM_DIR}/llvm" CACHE STRING "")
set(CLSPV_CLANG_SOURCE_DIR "${AMBER_CLSPV_LLVM_DIR}/clang" CACHE STRING "")
set(SPIRV_HEADERS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/spirv-headers" CACHE STRING "")
@@ -168,4 +181,8 @@ if (${AMBER_ENABLE_CLSPV})
set(LLVM_INCLUDE_UTILS OFF CACHE BOOL "")
add_subdirectory(${AMBER_CLSPV_DIR} ${CMAKE_CURRENT_BINARY_DIR}/clspv)
+
+ # TODO(asuonpaa): Using the latest LLVM gives multiple warnings of using deprecated
+ # arguments. Remove this when CLSPV doesn't use them.
+ add_compile_options(clspv, NO_DEPRECATED_FLAGS)
endif()
diff --git a/tools/roll-all b/tools/roll-all
index 97f00c3..48557e8 100755
--- a/tools/roll-all
+++ b/tools/roll-all
@@ -15,7 +15,6 @@
# Defined to use origin/master instead of origin/main
clspv=1
-clspv_llvm=1
cpplint=1
dxc=1
glslang=1
@@ -25,7 +24,6 @@ lodepng=1
spirv_headers=1
spirv_tools=1
swiftshader=1
-vulkan_headers=1
vulkan_loader=1
vulkan_validationlayers=1