Compare commits

..
Author SHA1 Message Date
Sungun Park cf75b4489b feedback 2025-02-04 13:41:42 -08:00
Sungun Park 923ac98ea8 Add multiview_data for multiview information
Add a varying variable `multiview_data` for both surface and
post-processing shaders. Currently this only works as intended in
surface shader, and additional implementation to facilitate it for
post-processing will be following.

The `multiview_data` contains multiview information like whether
multiview is enabled for the current material and what the eye index is
in that case. This variable is globally available including fragment
shaders so that it can be referenced in user shaders in .material files.
Also this allows us to indirectly reference the constant variables such
as `gl_ViewID_OVR` and `gl_ViewIndex` in a platform-agnostic way.

Make the preprocessor `MATERIAL_FEATURE_LEVEL` available for both
surface and post-processing shaders, it used to be only available for
surface shader, and this will be referenced in post-processing shaders
later to support multiview for post-processing.
2025-02-03 19:48:20 -08:00
Sungun Park 4fe852e88a Ensure correct resource cleanup sequence to avoid crashes upon app closing (#8408)
The commit 1747ae8f5a enfoces a correct
order for releasing resource. Fix the order to avoid crashes.

Make some samples to use the DEPTH32F format for better compatibility.
Some manufacturers don't fully support DEPTH24 on Vulkan. E.g., AMD
Radeon PRO W6400
2025-02-03 21:23:53 +00:00
Mathias Agopian 864529254e fix color grading as subpass
This broke in 48a2c64. Fixes #8401.
2025-02-03 12:37:53 -08:00
Powei Feng 93fa55bd29 vk: refactor utils into its own namespace (#8280)
We move the code that was contained within two "utils" files
into separate utils sources in the vulkan/utils directory.
2025-02-03 19:10:19 +00:00
Sungun Park fb9518e915 Fix warnings regarding #pragma clang (#8405)
'#pragma clang' is unavailable in MSVC. Wrap them with the proper
preprocessor to avoid warnings in MSVC.

BUGS=[390207431]
2025-02-03 17:43:44 +00:00
Mathias Agopian b780cb36d0 attempt to fix crashers when initializing the JVM
- clarify precondition for VirtualMachineEnv, in particular, 
  JNI_OnLoad() must be called from a thread attached to the VM, and
  should be called once. This is now enforced internally, subsequent
  calls are ignored.

- sVirtualMachine was written and read from potentially different 
  threads without synchronization. It is now mutex protected.

- added fatal asserts in all locations that we cannot recover from;
  previously we would stay in an undefined state.

BUGS=[390724273]
2025-02-01 22:35:53 -08:00
Rafael Dominguez 62cd8f1d35 Update multiview shader code generator for Vulkan
When targeting Vulkan with multiview, the shader
code generator was using the OpenGL extension
and built-in variables, which are not supported on
Vulkan.

Changed it to use GL_EXT_multiview instead of
GL_OVR_multiview2 when the target API is Vulkan.
2025-01-31 16:50:02 -08:00
Doris Wu 793f2b4eb7 [Depends on #8332] Integrate fgviewer to the engine side (#8344)
* Introduce FrameGraphInfo class

* Move the assignment into pimpl

* Make ctors explicit

* Add ctors to fg info structs

* Revert the macro change to align with existing

* Address the comments

* Remove pimpl and move func def to .cc

* Fix

* Convert the FrameGraph to FrameGraphInfo

* Initialize and update debug server on engine side

* Fix compile error

* Address the comments

* Update

* Use camelCase

* Use camelCase

* Update
2025-01-31 23:39:47 +00:00
Ben Doherty 9a2ca8ddbb Metal: add config to abandon frame if drawable cannot be acquired (#8397) 2025-01-31 13:31:07 -08:00
Eliza Velasquez 67710723d7 c-filament-style.el: fix init list indent 2025-01-31 12:06:09 -08:00
Eliza Velasquez 40851f4b51 matdbg: add support for essl1 shader debugging
Fixes #8261
2025-01-31 11:44:51 -08:00
Sungun Park 87bdf96449 Refactor: Rename shader snippets w/ new naming convention (see README.md) (#8402)
This commit renames all shader snippet files to conform to the newly
introduced naming convention outlined in README.md.

The new naming convention uses a `prefix_name.suffix` format to clearly
indicate the purpose and target shader stage of each snippet. This
improves the overall organization and readability of the shader code,
making it easier to understand how each snippet contributes to the
shader generation process.

No functional changes were made to the shader code itself or source
code. This is purely a refactoring for clarity and maintainability.
2025-01-31 00:02:53 +00:00
137 changed files with 1459 additions and 1096 deletions
+2
View File
@@ -7,3 +7,5 @@ for next branch cut* header.
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- matdbg: Add support for debugging ESSL 1.0 shaders
+2 -2
View File
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.56.8'
implementation 'com.google.android.filament:filament-android:1.56.7'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```shell
pod 'Filament', '~> 1.56.8'
pod 'Filament', '~> 1.56.7'
```
## Documentation
@@ -1271,7 +1271,7 @@ public class Engine {
* {@link android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed}.</p>
*/
public void flushAndWait() {
boolean unused = flushAndWait(Fence.WAIT_FOR_EVER);
flushAndWait(Fence.WAIT_FOR_EVER);
}
/**
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.56.8
VERSION_NAME=1.56.7
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+4 -4
View File
@@ -385,16 +385,16 @@ endforeach()
add_custom_command(
OUTPUT "${MATERIAL_DIR}/colorGrading.filamat"
DEPENDS ../shaders/src/dithering.fs
DEPENDS ../shaders/src/vignette.fs
DEPENDS ../shaders/src/inline_dithering.fs
DEPENDS ../shaders/src/inline_vignette.fs
DEPENDS src/materials/colorGrading/colorGrading.fs
APPEND
)
add_custom_command(
OUTPUT "${MATERIAL_DIR}/colorGradingAsSubpass.filamat"
DEPENDS ../shaders/src/dithering.fs
DEPENDS ../shaders/src/vignette.fs
DEPENDS ../shaders/src/inline_dithering.fs
DEPENDS ../shaders/src/inline_vignette.fs
DEPENDS src/materials/colorGrading/colorGrading.fs
APPEND
)
+9 -6
View File
@@ -185,8 +185,15 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/platform/VulkanPlatform.cpp
src/vulkan/platform/VulkanPlatformSwapChainImpl.cpp
src/vulkan/platform/VulkanPlatformSwapChainImpl.h
src/vulkan/spirv/VulkanSpirvUtils.cpp
src/vulkan/spirv/VulkanSpirvUtils.h
src/vulkan/utils/Conversion.cpp
src/vulkan/utils/Conversion.h
src/vulkan/utils/Definitions.h
src/vulkan/utils/Helper.h
src/vulkan/utils/Image.h
src/vulkan/utils/Image.cpp
src/vulkan/utils/Spirv.h
src/vulkan/utils/Spirv.cpp
src/vulkan/utils/StaticVector.h
src/vulkan/VulkanAsyncHandles.cpp
src/vulkan/VulkanAsyncHandles.h
src/vulkan/VulkanBlitter.cpp
@@ -205,8 +212,6 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/VulkanFboCache.h
src/vulkan/VulkanHandles.cpp
src/vulkan/VulkanHandles.h
src/vulkan/VulkanImageUtility.cpp
src/vulkan/VulkanImageUtility.h
src/vulkan/VulkanMemory.h
src/vulkan/VulkanMemory.cpp
src/vulkan/VulkanPipelineCache.cpp
@@ -221,8 +226,6 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/VulkanReadPixels.h
src/vulkan/VulkanTexture.cpp
src/vulkan/VulkanTexture.h
src/vulkan/VulkanUtility.cpp
src/vulkan/VulkanUtility.h
)
if (LINUX OR WIN32)
list(APPEND SRCS src/vulkan/platform/VulkanPlatformLinuxWindows.cpp)
@@ -1302,7 +1302,7 @@ enum class Workaround : uint16_t {
// for some uniform arrays, it's needed to do an initialization to avoid crash on adreno gpu
ADRENO_UNIFORM_ARRAY_CRASH,
// Workaround a Metal pipeline compilation error with the message:
// "Could not statically determine the target of a texture". See light_indirect.fs
// "Could not statically determine the target of a texture". See surface_light_indirect.fs
METAL_STATIC_TEXTURE_TARGET_ERROR,
// Adreno drivers sometimes aren't able to blit into a layer of a texture array.
DISABLE_BLIT_INTO_TEXTURE_ARRAY,
@@ -69,6 +69,16 @@ public:
virtual ShaderModel getShaderModel() const noexcept = 0;
// The shader language used for shaders for this driver, used to inform matdbg.
//
// For OpenGL, this distinguishes whether the driver's shaders are powered by ESSL1 or ESSL3.
// This information is used by matdbg to display the correct shader code to the web UI and patch
// the correct chunk when rebuilding shaders live.
//
// Metal shaders can either be MSL or Metal libraries, but at time of writing, matdbg can only
// interface with MSL.
virtual ShaderLanguage getShaderLanguage() const noexcept = 0;
// Returns the dispatcher. This is only called once during initialization of the CommandStream,
// so it doesn't matter that it's virtual.
virtual Dispatcher getDispatcher() const noexcept = 0;
@@ -126,8 +126,10 @@
* Driver API below...
*/
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
DECL_DRIVER_API_0(tick)
@@ -533,7 +535,9 @@ DECL_DRIVER_API_N(scissor,
Viewport, scissor)
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#undef EXPAND
@@ -18,7 +18,7 @@
#define TNT_FILAMENT_DRIVER_ANDROID_VIRTUAL_MACHINE_ENV_H
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Mutex.h>
#include <jni.h>
@@ -26,25 +26,17 @@ namespace filament {
class VirtualMachineEnv {
public:
// must be called before VirtualMachineEnv::get() from a thread that is attached to the JavaVM
static jint JNI_OnLoad(JavaVM* vm) noexcept;
static VirtualMachineEnv& get() noexcept {
// declaring this thread local, will ensure it's destroyed with the calling thread
static thread_local VirtualMachineEnv instance;
return instance;
}
// must be called on backend thread
static VirtualMachineEnv& get() noexcept;
static JNIEnv* getThreadEnvironment() noexcept {
JNIEnv* env;
assert_invariant(sVirtualMachine);
if (sVirtualMachine->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return nullptr; // this should not happen
}
return env;
}
// can be called from any thread that already has a JniEnv
static JNIEnv* getThreadEnvironment() noexcept;
inline JNIEnv* getEnvironment() noexcept {
assert_invariant(mVirtualMachine);
// must be called from the backend thread
JNIEnv* getEnvironment() noexcept {
JNIEnv* env = mJniEnv;
if (UTILS_UNLIKELY(!env)) {
return getEnvironmentSlow();
@@ -55,20 +47,14 @@ public:
static void handleException(JNIEnv* env) noexcept;
private:
VirtualMachineEnv() noexcept : mVirtualMachine(sVirtualMachine) {
// We're not initializing the JVM here -- but we could -- because most of the time
// we don't need the jvm. Instead we do the initialization on first use. This means we could get
// a nasty slow down the very first time, but we'll live with it for now.
}
~VirtualMachineEnv() {
if (mVirtualMachine) {
mVirtualMachine->DetachCurrentThread();
}
}
explicit VirtualMachineEnv(JavaVM* vm) noexcept;
~VirtualMachineEnv() noexcept;
JNIEnv* getEnvironmentSlow() noexcept;
static utils::Mutex sLock;
static JavaVM* sVirtualMachine;
static JavaVM* getVirtualMachine();
JNIEnv* mJniEnv = nullptr;
JavaVM* mVirtualMachine = nullptr;
};
+81 -16
View File
@@ -18,12 +18,28 @@
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Mutex.h>
#include <utils/Panic.h>
#include <jni.h>
#include <mutex>
namespace filament {
JavaVM* VirtualMachineEnv::sVirtualMachine = nullptr;
using namespace utils;
// This Mutex shouldn't be subject to the Static Initialization Order Fiasco because its initial state is
// a single int initialized to 0.
/* static*/ Mutex VirtualMachineEnv::sLock;
/* static*/ JavaVM* VirtualMachineEnv::sVirtualMachine = nullptr;
UTILS_NOINLINE
JavaVM* VirtualMachineEnv::getVirtualMachine() {
std::lock_guard const lock(sLock);
assert_invariant(sVirtualMachine);
return sVirtualMachine;
}
/*
* This is typically called by filament_jni.so when it is loaded. If filament_jni.so is not used,
@@ -35,15 +51,75 @@ JavaVM* VirtualMachineEnv::sVirtualMachine = nullptr;
UTILS_PUBLIC
UTILS_NOINLINE
jint VirtualMachineEnv::JNI_OnLoad(JavaVM* vm) noexcept {
JNIEnv* env = nullptr;
if (UTILS_UNLIKELY(vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)) {
// this should not happen
return -1;
std::lock_guard const lock(sLock);
if (sVirtualMachine) {
// It doesn't make sense for JNI_OnLoad() to be called more than once
return JNI_VERSION_1_6;
}
// Here we check this VM at least has JNI_VERSION_1_6
JNIEnv* env = nullptr;
jint const result = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
FILAMENT_CHECK_POSTCONDITION(result == JNI_OK)
<< "Couldn't get JniEnv* from the VM, error = " << result;
sVirtualMachine = vm;
return JNI_VERSION_1_6;
}
UTILS_NOINLINE
VirtualMachineEnv& VirtualMachineEnv::get() noexcept {
JavaVM* const vm = getVirtualMachine();
// declaring this thread local, will ensure it's destroyed with the calling thread
thread_local VirtualMachineEnv instance{ vm };
return instance;
}
UTILS_NOINLINE
JNIEnv* VirtualMachineEnv::getThreadEnvironment() noexcept {
JavaVM* const vm = getVirtualMachine();
JNIEnv* env = nullptr;
jint const result = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
FILAMENT_CHECK_POSTCONDITION(result == JNI_OK)
<< "Couldn't get JniEnv* from the VM, error = " << result;
return env;
}
VirtualMachineEnv::VirtualMachineEnv(JavaVM* vm) noexcept : mVirtualMachine(vm) {
// We're not initializing the JVM here -- but we could -- because most of the time
// we don't need the jvm. Instead, we do the initialization on first use. This means we could get
// a nasty slow down the very first time, but we'll live with it for now.
}
VirtualMachineEnv::~VirtualMachineEnv() noexcept {
if (mVirtualMachine) {
mVirtualMachine->DetachCurrentThread();
}
}
UTILS_NOINLINE
JNIEnv* VirtualMachineEnv::getEnvironmentSlow() noexcept {
FILAMENT_CHECK_PRECONDITION(mVirtualMachine)
<< "JNI_OnLoad() has not been called";
#if defined(__ANDROID__)
jint const result = mVirtualMachine->AttachCurrentThread(&mJniEnv, nullptr);
#else
jint const result = mVirtualMachine->AttachCurrentThread(reinterpret_cast<void**>(&mJniEnv), nullptr);
#endif
FILAMENT_CHECK_POSTCONDITION(result == JNI_OK)
<< "JavaVM::AttachCurrentThread failed with error " << result;
FILAMENT_CHECK_POSTCONDITION(mJniEnv)
<< "JavaVM::AttachCurrentThread returned a null mJniEnv";
return mJniEnv;
}
UTILS_NOINLINE
void VirtualMachineEnv::handleException(JNIEnv* const env) noexcept {
if (UTILS_UNLIKELY(env->ExceptionCheck())) {
@@ -52,16 +128,5 @@ void VirtualMachineEnv::handleException(JNIEnv* const env) noexcept {
}
}
UTILS_NOINLINE
JNIEnv* VirtualMachineEnv::getEnvironmentSlow() noexcept {
#if defined(__ANDROID__)
mVirtualMachine->AttachCurrentThread(&mJniEnv, nullptr);
#else
mVirtualMachine->AttachCurrentThread(reinterpret_cast<void**>(&mJniEnv), nullptr);
#endif
assert_invariant(mJniEnv);
return mJniEnv;
}
} // namespace filament
+1
View File
@@ -67,6 +67,7 @@ private:
MetalContext* mContext;
ShaderModel getShaderModel() const noexcept final;
ShaderLanguage getShaderLanguage() const noexcept final;
// Overrides the default implementation by wrapping the call to fn in an @autoreleasepool block.
void execute(std::function<void(void)> const& fn) noexcept final;
+6 -2
View File
@@ -947,6 +947,10 @@ ShaderModel MetalDriver::getShaderModel() const noexcept {
#endif
}
ShaderLanguage MetalDriver::getShaderLanguage() const noexcept {
return ShaderLanguage::MSL;
}
Handle<HwStream> MetalDriver::createStreamNative(void* stream) {
return {};
}
@@ -1135,8 +1139,8 @@ FeatureLevel MetalDriver::getFeatureLevel() {
math::float2 MetalDriver::getClipSpaceParams() {
// virtual and physical z-coordinate of clip-space is in [-w, 0]
// Note: this is actually never used (see: main.vs), but it's a backend API so we implement it
// properly.
// Note: this is actually never used (see: surface_main.vs), but it's a backend API so we
// implement it properly.
return math::float2{ 1.0f, 0.0f };
}
+4
View File
@@ -39,6 +39,10 @@ ShaderModel NoopDriver::getShaderModel() const noexcept {
#endif
}
ShaderLanguage NoopDriver::getShaderLanguage() const noexcept {
return ShaderLanguage::ESSL3;
}
// explicit instantiation of the Dispatcher
template class ConcreteDispatcher<NoopDriver>;
+1
View File
@@ -34,6 +34,7 @@ public:
private:
ShaderModel getShaderModel() const noexcept final;
ShaderLanguage getShaderLanguage() const noexcept final;
uint64_t nextFakeHandle = 1;
@@ -75,9 +75,11 @@
#include <emscripten.h>
#endif
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
#endif
// We can only support this feature on OpenGL ES 3.1+
// Support is currently disabled as we don't need it
@@ -349,6 +351,10 @@ ShaderModel OpenGLDriver::getShaderModel() const noexcept {
return mContext.getShaderModel();
}
ShaderLanguage OpenGLDriver::getShaderLanguage() const noexcept {
return mContext.isES2() ? ShaderLanguage::ESSL1 : ShaderLanguage::ESSL3;
}
// ------------------------------------------------------------------------------------------------
// Change and track GL state
// ------------------------------------------------------------------------------------------------
@@ -4090,4 +4096,6 @@ template class ConcreteDispatcher<OpenGLDriver>;
} // namespace filament::backend
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
@@ -204,6 +204,7 @@ private:
}
ShaderModel getShaderModel() const noexcept final;
ShaderLanguage getShaderLanguage() const noexcept final;
/*
* Driver interface
@@ -16,13 +16,28 @@
#include "ExternalStreamManagerAndroid.h"
#include <utils/api_level.h>
#include <private/backend/VirtualMachineEnv.h>
#include <backend/Platform.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Log.h>
#include <utils/ostream.h>
#include <dlfcn.h>
#if __has_include(<android/surface_texture.h>)
# include <android/surface_texture.h>
# include <android/surface_texture_jni.h>
#else
struct ASurfaceTexture;
typedef struct ASurfaceTexture ASurfaceTexture;
#endif
#include <chrono>
#include <jni.h>
#include <stdint.h>
#include <new>
using namespace utils;
@@ -32,13 +47,8 @@ using namespace backend;
using Stream = Platform::Stream;
template <typename T>
static void loadSymbol(T*& pfn, const char *symbol) noexcept {
pfn = (T*)dlsym(RTLD_DEFAULT, symbol);
}
ExternalStreamManagerAndroid& ExternalStreamManagerAndroid::create() noexcept {
return *(new ExternalStreamManagerAndroid{});
return *(new(std::nothrow) ExternalStreamManagerAndroid{});
}
void ExternalStreamManagerAndroid::destroy(ExternalStreamManagerAndroid* pExternalStreamManagerAndroid) noexcept {
@@ -56,23 +66,13 @@ ExternalStreamManagerAndroid::~ExternalStreamManagerAndroid() noexcept = default
UTILS_NOINLINE
JNIEnv* ExternalStreamManagerAndroid::getEnvironmentSlow() noexcept {
JNIEnv * env = mVm.getEnvironment();
JNIEnv* const env = mVm.getEnvironment();
mJniEnv = env;
jclass SurfaceTextureClass = env->FindClass("android/graphics/SurfaceTexture");
mSurfaceTextureClass_updateTexImage = env->GetMethodID(
SurfaceTextureClass, "updateTexImage", "()V");
mSurfaceTextureClass_attachToGLContext = env->GetMethodID(
SurfaceTextureClass, "attachToGLContext", "(I)V");
mSurfaceTextureClass_detachFromGLContext = env->GetMethodID(
SurfaceTextureClass, "detachFromGLContext", "()V");
mSurfaceTextureClass_getTimestamp = env->GetMethodID(
SurfaceTextureClass, "getTimestamp", "()J");
mSurfaceTextureClass_updateTexImage = env->GetMethodID(SurfaceTextureClass, "updateTexImage", "()V");
mSurfaceTextureClass_attachToGLContext = env->GetMethodID(SurfaceTextureClass, "attachToGLContext", "(I)V");
mSurfaceTextureClass_detachFromGLContext = env->GetMethodID(SurfaceTextureClass, "detachFromGLContext", "()V");
mSurfaceTextureClass_getTimestamp = env->GetMethodID(SurfaceTextureClass, "getTimestamp", "()J");
return env;
}
@@ -82,7 +82,7 @@ Stream* ExternalStreamManagerAndroid::acquire(jobject surfaceTexture) noexcept {
if (!env) {
return nullptr; // this should not happen
}
EGLStream* stream = new EGLStream();
EGLStream* stream = new(std::nothrow) EGLStream();
stream->jSurfaceTexture = env->NewGlobalRef(surfaceTexture);
if (__builtin_available(android 28, *)) {
stream->nSurfaceTexture = ASurfaceTexture_fromSurfaceTexture(env, surfaceTexture);
@@ -91,29 +91,30 @@ Stream* ExternalStreamManagerAndroid::acquire(jobject surfaceTexture) noexcept {
}
void ExternalStreamManagerAndroid::release(Stream* handle) noexcept {
EGLStream* stream = static_cast<EGLStream*>(handle);
EGLStream const* stream = static_cast<EGLStream*>(handle);
if (__builtin_available(android 28, *)) {
ASurfaceTexture_release(stream->nSurfaceTexture);
}
JNIEnv* const env = getEnvironment();
// use VirtualMachineEnv::getEnvironment() directly because we don't need to cache JNI methods here
JNIEnv* const env = mVm.getEnvironment();
assert_invariant(env); // we should have called attach() by now
env->DeleteGlobalRef(stream->jSurfaceTexture);
delete stream;
}
void ExternalStreamManagerAndroid::attach(Stream* handle, intptr_t tname) noexcept {
EGLStream* stream = static_cast<EGLStream*>(handle);
EGLStream const* stream = static_cast<EGLStream*>(handle);
if (__builtin_available(android 28, *)) {
// associate our GL texture to the SurfaceTexture
ASurfaceTexture* const aSurfaceTexture = stream->nSurfaceTexture;
if (UTILS_UNLIKELY(ASurfaceTexture_attachToGLContext(aSurfaceTexture, (uint32_t)tname))) {
if (UTILS_UNLIKELY(ASurfaceTexture_attachToGLContext(aSurfaceTexture, uint32_t(tname)))) {
// Unfortunately, before API 26 SurfaceTexture was always created in attached mode,
// so attachToGLContext can fail. We consider this the unlikely case, because
// this is how it should work.
// So now we have to detach the surfacetexture from its texture
ASurfaceTexture_detachFromGLContext(aSurfaceTexture);
// and finally, try attaching again
ASurfaceTexture_attachToGLContext(aSurfaceTexture, (uint32_t)tname);
ASurfaceTexture_attachToGLContext(aSurfaceTexture, uint32_t(tname));
}
} else {
JNIEnv* const env = getEnvironment();
@@ -121,19 +122,19 @@ void ExternalStreamManagerAndroid::attach(Stream* handle, intptr_t tname) noexce
// associate our GL texture to the SurfaceTexture
jobject jSurfaceTexture = stream->jSurfaceTexture;
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_attachToGLContext, (jint)tname);
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_attachToGLContext, jint(tname));
if (UTILS_UNLIKELY(env->ExceptionCheck())) {
// Unfortunately, before API 26 SurfaceTexture was always created in attached mode,
// so attachToGLContext can fail. We consider this the unlikely case, because
// this is how it should work.
env->ExceptionClear();
// so now we have to detach the surfacetexture from its texture
// so now we have to detach the SurfaceTexture from its texture
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_detachFromGLContext);
VirtualMachineEnv::handleException(env);
// and finally, try attaching again
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_attachToGLContext, (jint)tname);
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_attachToGLContext, jint(tname));
VirtualMachineEnv::handleException(env);
}
}
@@ -144,7 +145,7 @@ void ExternalStreamManagerAndroid::detach(Stream* handle) noexcept {
if (__builtin_available(android 28, *)) {
ASurfaceTexture_detachFromGLContext(stream->nSurfaceTexture);
} else {
JNIEnv* const env = mVm.getEnvironment();
JNIEnv* const env = getEnvironment();
assert_invariant(env); // we should have called attach() by now
env->CallVoidMethod(stream->jSurfaceTexture, mSurfaceTextureClass_detachFromGLContext);
VirtualMachineEnv::handleException(env);
@@ -152,12 +153,12 @@ void ExternalStreamManagerAndroid::detach(Stream* handle) noexcept {
}
void ExternalStreamManagerAndroid::updateTexImage(Stream* handle, int64_t* timestamp) noexcept {
EGLStream* stream = static_cast<EGLStream*>(handle);
EGLStream const* stream = static_cast<EGLStream*>(handle);
if (__builtin_available(android 28, *)) {
ASurfaceTexture_updateTexImage(stream->nSurfaceTexture);
*timestamp = ASurfaceTexture_getTimestamp(stream->nSurfaceTexture);
} else {
JNIEnv* const env = mVm.getEnvironment();
JNIEnv* const env = getEnvironment();
assert_invariant(env); // we should have called attach() by now
env->CallVoidMethod(stream->jSurfaceTexture, mSurfaceTextureClass_updateTexImage);
VirtualMachineEnv::handleException(env);
@@ -21,14 +21,19 @@
#include <backend/Platform.h>
#include <utils/compiler.h>
#if __has_include(<android/surface_texture.h>)
# include <android/surface_texture.h>
# include <android/surface_texture_jni.h>
#else
struct ASurfaceTexture;
typedef struct ASurfaceTexture ASurfaceTexture;
#endif
#include <jni.h>
#include <stdint.h>
namespace filament::backend {
/*
@@ -70,7 +75,8 @@ private:
ASurfaceTexture* nSurfaceTexture = nullptr;
};
inline JNIEnv* getEnvironment() noexcept {
// Must only be called from the backend thread
JNIEnv* getEnvironment() noexcept {
JNIEnv* env = mJniEnv;
if (UTILS_UNLIKELY(!env)) {
return getEnvironmentSlow();
@@ -85,7 +91,6 @@ private:
jmethodID mSurfaceTextureClass_attachToGLContext{};
jmethodID mSurfaceTextureClass_detachFromGLContext{};
};
} // namespace filament::backend
#endif //TNT_FILAMENT_BACKEND_OPENGL_ANDROID_EXTERNAL_STREAM_MANAGER_ANDROID_H
@@ -21,6 +21,7 @@
#include "VulkanHandles.h"
#include "VulkanSamplerCache.h"
#include "VulkanTexture.h"
#include "vulkan/utils/Image.h"
#include <utils/FixedCapacityVector.h>
#include <utils/Panic.h>
@@ -61,8 +62,8 @@ inline void blitFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect, V
.dstOffsets = { dstRect[0], dstRect[1] },
}};
vkCmdBlitImage(cmdbuf,
src.getImage(), imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC),
dst.getImage(), imgutil::getVkLayout(VulkanLayout::TRANSFER_DST),
src.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC),
dst.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_DST),
1, blitRegions, filter);
if (oldSrcLayout == VulkanLayout::UNDEFINED) {
@@ -104,8 +105,8 @@ inline void resolveFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect
.extent = { src.getExtent2D().width, src.getExtent2D().height, 1 },
}};
vkCmdResolveImage(cmdbuffer,
src.getImage(), imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC),
dst.getImage(), imgutil::getVkLayout(VulkanLayout::TRANSFER_DST),
src.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC),
dst.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_DST),
1, resolveRegions);
if (oldSrcLayout == VulkanLayout::UNDEFINED) {
+3 -3
View File
@@ -23,8 +23,8 @@
#include "VulkanAsyncHandles.h"
#include "VulkanConstants.h"
#include "VulkanUtility.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/StaticVector.h"
#include <utils/Condition.h>
#include <utils/FixedCapacityVector.h>
@@ -79,7 +79,7 @@ struct VulkanCommandBuffer {
void reset() noexcept;
inline void insertWait(VkSemaphore sem) {
mWaitSemaphores.insert(sem);
mWaitSemaphores.push_back(sem);
}
void pushMarker(char const* marker) noexcept;
@@ -115,7 +115,7 @@ private:
bool const isProtected;
VkDevice mDevice;
VkQueue mQueue;
CappedArray<VkSemaphore, 2> mWaitSemaphores;
fvkutils::StaticVector<VkSemaphore, 2> mWaitSemaphores;
VkCommandBuffer mBuffer;
VkSemaphore mSubmission;
VkFence mFence;
@@ -20,7 +20,6 @@
#include "VulkanHandles.h"
#include "VulkanMemory.h"
#include "VulkanTexture.h"
#include "VulkanUtility.h"
#include <backend/PixelBufferDescriptor.h>
+10 -19
View File
@@ -18,8 +18,8 @@
#define TNT_FILAMENT_BACKEND_VULKANCONTEXT_H
#include "VulkanConstants.h"
#include "VulkanImageUtility.h"
#include "VulkanUtility.h"
#include "vulkan/utils/Image.h"
#include "vulkan/utils/Definitions.h"
#include "vulkan/memory/ResourcePointer.h"
@@ -28,6 +28,8 @@
#include <utils/Mutex.h>
#include <utils/Slice.h>
#include <bluevk/BlueVK.h>
#include <memory>
VK_DEFINE_HANDLE(VmaAllocator)
@@ -113,11 +115,11 @@ public:
return (uint32_t) VK_MAX_MEMORY_TYPES;
}
inline VkFormatList const& getAttachmentDepthStencilFormats() const {
inline fvkutils::VkFormatList const& getAttachmentDepthStencilFormats() const {
return mDepthStencilFormats;
}
inline VkFormatList const& getBlittableDepthStencilFormats() const {
inline fvkutils::VkFormatList const& getBlittableDepthStencilFormats() const {
return mBlittableDepthStencilFormats;
}
@@ -161,24 +163,13 @@ public:
return mProtectedMemorySupported;
}
inline bool isImageView2DOn3DImageSupported() const noexcept {
return mPortabilitySubsetFeatures.imageView2DOn3DImage == VK_TRUE;
}
private:
VkPhysicalDeviceMemoryProperties mMemoryProperties = {};
VkPhysicalDeviceProperties2 mPhysicalDeviceProperties = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
};
VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
};
VkPhysicalDevicePortabilitySubsetFeaturesKHR mPortabilitySubsetFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
// By default, on platforms where we don't have portability subset, then this feature must
// exists. We only fill this struct only when portability subset is needed (i.e.
// non-conformant vulkan implementation).
.imageView2DOn3DImage = VK_TRUE,
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
};
bool mDebugMarkersSupported = false;
bool mDebugUtilsSupported = false;
@@ -186,8 +177,8 @@ private:
bool mLazilyAllocatedMemorySupported = false;
bool mProtectedMemorySupported = false;
VkFormatList mDepthStencilFormats;
VkFormatList mBlittableDepthStencilFormats;
fvkutils::VkFormatList mDepthStencilFormats;
fvkutils::VkFormatList mBlittableDepthStencilFormats;
// For convenience so that VulkanPlatform can initialize the private fields.
friend class VulkanPlatform;
+34 -24
View File
@@ -26,9 +26,12 @@
#include "VulkanHandles.h"
#include "VulkanMemory.h"
#include "VulkanTexture.h"
#include "memory/ResourceManager.h"
#include "memory/ResourcePointer.h"
#include "vulkan/memory/ResourceManager.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Conversion.h"
#include "vulkan/utils/Definitions.h"
#include <backend/DriverEnums.h>
#include <backend/platforms/VulkanPlatform.h>
#include <utils/CString.h>
@@ -43,11 +46,13 @@ using namespace bluevk;
using utils::FixedCapacityVector;
#if defined(__clang__)
// Vulkan functions often immediately dereference pointers, so it's fine to pass in a pointer
// to a stack-allocated variable.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-stack-address"
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
namespace filament::backend {
@@ -295,6 +300,10 @@ ShaderModel VulkanDriver::getShaderModel() const noexcept {
#endif
}
ShaderLanguage VulkanDriver::getShaderLanguage() const noexcept {
return ShaderLanguage::SPIRV;
}
void VulkanDriver::terminate() {
// Flush and wait here to make sure all queued commands are executed and resources that are tied
// to those commands are no longer referenced.
@@ -536,16 +545,16 @@ void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
backend::TextureSwizzle a) {
TextureSwizzle const swizzleArray[] = {r, g, b, a};
VkComponentMapping const swizzle = getSwizzleMap(swizzleArray);
VkComponentMapping const swizzle = fvkutils::getSwizzleMap(swizzleArray);
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, swizzle);
texture.inc();
}
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th,
backend::SamplerType target, backend::TextureFormat format,
uint32_t width, uint32_t height, backend::TextureUsage usage, void* externalImage) {
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* externalImage) {
FVK_SYSTRACE_SCOPE();
const auto& metadata = mPlatform->getExternalImageMetadata(externalImage);
@@ -555,7 +564,7 @@ void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th,
assert_invariant(width == metadata.width);
assert_invariant(height == metadata.height);
assert_invariant(getVkFormat(format) == metadata.format);
assert_invariant(fvkutils::getVkFormat(format) == metadata.format);
const auto& data = mPlatform->createExternalImage(externalImage, metadata);
@@ -930,7 +939,7 @@ FenceStatus VulkanDriver::getFenceStatus(Handle<HwFence> fh) {
// We create all textures using VK_IMAGE_TILING_OPTIMAL, so our definition of "supported" is that
// the GPU supports the given texture format with non-zero optimal tiling features.
bool VulkanDriver::isTextureFormatSupported(TextureFormat format) {
VkFormat vkformat = getVkFormat(format);
VkFormat vkformat = fvkutils::getVkFormat(format);
if (vkformat == VK_FORMAT_UNDEFINED) {
return false;
}
@@ -957,7 +966,7 @@ bool VulkanDriver::isTextureFormatMipmappable(TextureFormat format) {
}
bool VulkanDriver::isRenderTargetFormatSupported(TextureFormat format) {
VkFormat vkformat = getVkFormat(format);
VkFormat vkformat = fvkutils::getVkFormat(format);
if (vkformat == VK_FORMAT_UNDEFINED) {
return false;
}
@@ -1015,12 +1024,11 @@ bool VulkanDriver::isDepthStencilResolveSupported() {
bool VulkanDriver::isDepthStencilBlitSupported(TextureFormat format) {
auto const& formats = mContext.getBlittableDepthStencilFormats();
return std::find(formats.begin(), formats.end(), getVkFormat(format)) != formats.end();
return std::find(formats.begin(), formats.end(), fvkutils::getVkFormat(format)) !=
formats.end();
}
bool VulkanDriver::isProtectedTexturesSupported() {
return false;
}
bool VulkanDriver::isProtectedTexturesSupported() { return false; }
bool VulkanDriver::isDepthClampSupported() {
return mContext.isDepthClampSupported();
@@ -1091,8 +1099,8 @@ FeatureLevel VulkanDriver::getFeatureLevel() {
math::float2 VulkanDriver::getClipSpaceParams() {
// virtual and physical z-coordinate of clip-space is in [-w, 0]
// Note: this is actually never used (see: main.vs), but it's a backend API, so we implement it
// properly.
// Note: this is actually never used (see: surface_main.vs), but it's a backend API, so we
// implement it properly.
return math::float2{ 1.0f, 0.0f };
}
@@ -1673,25 +1681,25 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
auto rt = mCurrentRenderPass.renderTarget;
VulkanPipelineCache::RasterState const vulkanRasterState{
.cullMode = getCullMode(rasterState.culling),
.frontFace = getFrontFace(rasterState.inverseFrontFaces),
.cullMode = fvkutils::getCullMode(rasterState.culling),
.frontFace = fvkutils::getFrontFace(rasterState.inverseFrontFaces),
.depthBiasEnable = (depthOffset.constant || depthOffset.slope) ? true : false,
.blendEnable = rasterState.hasBlending(),
.depthWriteEnable = rasterState.depthWrite,
.alphaToCoverageEnable = rasterState.alphaToCoverage,
.srcColorBlendFactor = getBlendFactor(rasterState.blendFunctionSrcRGB),
.dstColorBlendFactor = getBlendFactor(rasterState.blendFunctionDstRGB),
.srcAlphaBlendFactor = getBlendFactor(rasterState.blendFunctionSrcAlpha),
.dstAlphaBlendFactor = getBlendFactor(rasterState.blendFunctionDstAlpha),
.srcColorBlendFactor = fvkutils::getBlendFactor(rasterState.blendFunctionSrcRGB),
.dstColorBlendFactor = fvkutils::getBlendFactor(rasterState.blendFunctionDstRGB),
.srcAlphaBlendFactor = fvkutils::getBlendFactor(rasterState.blendFunctionSrcAlpha),
.dstAlphaBlendFactor = fvkutils::getBlendFactor(rasterState.blendFunctionDstAlpha),
.colorWriteMask = (VkColorComponentFlags) (rasterState.colorWrite ? 0xf : 0x0),
.rasterizationSamples = rt->getSamples(),
.depthClamp = rasterState.depthClamp,
.colorTargetCount = rt->getColorTargetCount(mCurrentRenderPass),
.colorBlendOp = rasterState.blendEquationRGB,
.alphaBlendOp = rasterState.blendEquationAlpha,
.alphaBlendOp = rasterState.blendEquationAlpha,
.depthCompareOp = rasterState.depthFunc,
.depthBiasConstantFactor = depthOffset.constant,
.depthBiasSlopeFactor = depthOffset.slope
.depthBiasSlopeFactor = depthOffset.slope,
};
// unfortunately in Vulkan the topology is per pipeline
@@ -1728,7 +1736,7 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
mBoundPipeline = {
.program = program,
.pipelineLayout = pipelineLayout,
.descriptorSetMask = DescriptorSetMask(descriptorSetMaskTable[layoutCount]),
.descriptorSetMask = fvkutils::DescriptorSetMask(descriptorSetMaskTable[layoutCount]),
};
mPipelineCache.bindLayout(pipelineLayout);
@@ -1877,4 +1885,6 @@ template class ConcreteDispatcher<VulkanDriver>;
} // namespace filament::backend
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
+10 -7
View File
@@ -26,12 +26,13 @@
#include "VulkanReadPixels.h"
#include "VulkanSamplerCache.h"
#include "VulkanStagePool.h"
#include "VulkanUtility.h"
#include "vulkan/caching/VulkanDescriptorSetManager.h"
#include "vulkan/caching/VulkanPipelineLayoutCache.h"
#include "vulkan/memory/ResourceManager.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Definitions.h"
#include "backend/DriverEnums.h"
#include "caching/VulkanDescriptorSetManager.h"
#include "caching/VulkanPipelineLayoutCache.h"
#include "memory/ResourceManager.h"
#include "memory/ResourcePointer.h"
#include "DriverBase.h"
#include "private/backend/Driver.h"
@@ -93,6 +94,7 @@ private:
Dispatcher getDispatcher() const noexcept final;
ShaderModel getShaderModel() const noexcept final;
ShaderLanguage getShaderLanguage() const noexcept final;
template<typename T>
friend class ConcreteDispatcher;
@@ -141,13 +143,14 @@ private:
struct {
resource_ptr<VulkanProgram> program;
VkPipelineLayout pipelineLayout;
DescriptorSetMask descriptorSetMask;
fvkutils::DescriptorSetMask descriptorSetMask;
} mBoundPipeline = {};
// We need to store information about a render pass to enable better barriers at the end of a
// renderpass.
struct {
using AttachmentArray = CappedArray<VulkanAttachment, MAX_RENDERTARGET_ATTACHMENT_TEXTURES>;
using AttachmentArray =
fvkutils::StaticVector<VulkanAttachment, MAX_RENDERTARGET_ATTACHMENT_TEXTURES>;
AttachmentArray attachments;
} mRenderPassFboInfo = {};
+13 -13
View File
@@ -14,12 +14,12 @@
* limitations under the License.
*/
#include "vulkan/VulkanFboCache.h"
#include <utils/Panic.h>
#include "VulkanFboCache.h"
#include "VulkanConstants.h"
#include "VulkanUtility.h"
#include "vulkan/utils/Image.h"
#include <utils/Panic.h>
// If any VkRenderPass or VkFramebuffer is unused for more than TIME_BEFORE_EVICTION frames, it
// is evicted from the cache.
@@ -214,7 +214,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
if (config.colorFormat[i] == VK_FORMAT_UNDEFINED) {
continue;
}
const VkImageLayout subpassLayout = imgutil::getVkLayout(VulkanLayout::COLOR_ATTACHMENT);
const VkImageLayout subpassLayout = fvkutils::getVkLayout(VulkanLayout::COLOR_ATTACHMENT);
uint32_t index;
if (!hasSubpasses) {
@@ -259,8 +259,8 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
.storeOp = (config.usesLazilyAllocatedMemory & (1 << i)) ? kDisableStore : kEnableStore,
.stencilLoadOp = kDontCare,
.stencilStoreOp = kDisableStore,
.initialLayout = imgutil::getVkLayout(VulkanLayout::COLOR_ATTACHMENT),
.finalLayout = imgutil::getVkLayout(FINAL_COLOR_ATTACHMENT_LAYOUT),
.initialLayout = fvkutils::getVkLayout(VulkanLayout::COLOR_ATTACHMENT),
.finalLayout = fvkutils::getVkLayout(FINAL_COLOR_ATTACHMENT_LAYOUT),
};
}
@@ -287,7 +287,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
pResolveAttachment->attachment = attachmentIndex;
pResolveAttachment->layout
= imgutil::getVkLayout(VulkanLayout::COLOR_ATTACHMENT_RESOLVE);
= fvkutils::getVkLayout(VulkanLayout::COLOR_ATTACHMENT_RESOLVE);
++pResolveAttachment;
attachments[attachmentIndex++] = {
@@ -297,8 +297,8 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
.storeOp = kEnableStore,
.stencilLoadOp = kDontCare,
.stencilStoreOp = kDisableStore,
.initialLayout = imgutil::getVkLayout(VulkanLayout::COLOR_ATTACHMENT),
.finalLayout = imgutil::getVkLayout(FINAL_COLOR_ATTACHMENT_LAYOUT),
.initialLayout = fvkutils::getVkLayout(VulkanLayout::COLOR_ATTACHMENT),
.finalLayout = fvkutils::getVkLayout(FINAL_COLOR_ATTACHMENT_LAYOUT),
};
}
@@ -307,7 +307,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
const bool clear = any(config.clear & TargetBufferFlags::DEPTH);
const bool discardStart = any(config.discardStart & TargetBufferFlags::DEPTH);
const bool discardEnd = any(config.discardEnd & TargetBufferFlags::DEPTH);
depthAttachmentRef.layout = imgutil::getVkLayout(VulkanLayout::DEPTH_ATTACHMENT);
depthAttachmentRef.layout = fvkutils::getVkLayout(VulkanLayout::DEPTH_ATTACHMENT);
depthAttachmentRef.attachment = attachmentIndex;
attachments[attachmentIndex++] = {
.format = config.depthFormat,
@@ -316,8 +316,8 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
.storeOp = discardEnd ? kDisableStore : kEnableStore,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = imgutil::getVkLayout(config.initialDepthLayout),
.finalLayout = imgutil::getVkLayout(FINAL_DEPTH_ATTACHMENT_LAYOUT),
.initialLayout = fvkutils::getVkLayout(config.initialDepthLayout),
.finalLayout = fvkutils::getVkLayout(FINAL_DEPTH_ATTACHMENT_LAYOUT),
};
}
renderPassInfo.attachmentCount = attachmentIndex;
+10 -8
View File
@@ -22,9 +22,11 @@
#include "VulkanDriver.h"
#include "VulkanMemory.h"
#include "VulkanUtility.h"
#include "vulkan/memory/ResourcePointer.h"
#include "spirv/VulkanSpirvUtils.h"
#include "vulkan/utils/Conversion.h"
#include "vulkan/utils/Definitions.h"
#include "vulkan/utils/Image.h"
#include "vulkan/utils/Spirv.h"
#include <backend/platforms/VulkanPlatform.h>
@@ -56,10 +58,10 @@ template<typename Bitmask>
inline void fromStageFlags(backend::ShaderStageFlags stage, descriptor_binding_t binding,
Bitmask& mask) {
if ((bool) (stage & ShaderStageFlags::VERTEX)) {
mask.set(binding + getVertexStageShift<Bitmask>());
mask.set(binding + fvkutils::getVertexStageShift<Bitmask>());
}
if ((bool) (stage & ShaderStageFlags::FRAGMENT)) {
mask.set(binding + getFragmentStageShift<Bitmask>());
mask.set(binding + fvkutils::getFragmentStageShift<Bitmask>());
}
}
@@ -206,7 +208,7 @@ VulkanProgram::VulkanProgram(VkDevice device, Program const& builder) noexcept
size_t dataSize = blob.size();
if (!specializationConstants.empty()) {
workaroundSpecConstant(blob, specializationConstants, shader);
fvkutils::workaroundSpecConstant(blob, specializationConstants, shader);
data = (uint32_t*) shader.data();
dataSize = shader.size() * 4;
}
@@ -314,8 +316,8 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
// Constrain the sample count according to both kinds of sample count masks obtained from
// VkPhysicalDeviceProperties. This is consistent with the VulkanTexture constructor.
auto const& limits = context.getPhysicalDeviceLimits();
samples = reduceSampleCount(samples, limits.framebufferDepthSampleCounts &
limits.framebufferColorSampleCounts);
samples = samples = fvkutils::reduceSampleCount(samples,
limits.framebufferDepthSampleCounts & limits.framebufferColorSampleCounts);
auto& rpkey = mInfo->rpkey;
rpkey.samples = samples;
@@ -498,7 +500,7 @@ VulkanVertexBufferInfo::VulkanVertexBufferInfo(
Attribute attrib = attributes[attribIndex];
bool const isInteger = attrib.flags & Attribute::FLAG_INTEGER_TARGET;
bool const isNormalized = attrib.flags & Attribute::FLAG_NORMALIZED;
VkFormat vkformat = getVkFormat(attrib.type, isNormalized, isInteger);
VkFormat vkformat = fvkutils::getVkFormat(attrib.type, isNormalized, isInteger);
// HACK: Re-use the positions buffer as a dummy buffer for disabled attributes. Filament's
// vertex shaders declare all attributes as either vec4 or uvec4 (the latter for bone
+13 -12
View File
@@ -25,8 +25,9 @@
#include "VulkanFboCache.h"
#include "VulkanSwapChain.h"
#include "VulkanTexture.h"
#include "VulkanUtility.h"
#include "vulkan/memory/Resource.h"
#include "vulkan/utils/StaticVector.h"
#include "vulkan/utils/Definitions.h"
#include <backend/Program.h>
@@ -44,11 +45,11 @@ namespace {
template<typename Bitmask>
inline uint8_t collapsedCount(Bitmask const& mask) {
static_assert(sizeof(mask) <= 64);
constexpr uint64_t VERTEX_MASK = (1ULL << getFragmentStageShift<Bitmask>()) - 1ULL;
constexpr uint64_t FRAGMENT_MASK = (VERTEX_MASK << getFragmentStageShift<Bitmask>());
constexpr uint64_t VERTEX_MASK = (1ULL << fvkutils::getFragmentStageShift<Bitmask>()) - 1ULL;
constexpr uint64_t FRAGMENT_MASK = (VERTEX_MASK << fvkutils::getFragmentStageShift<Bitmask>());
uint64_t val = mask.getValue();
val = ((val & VERTEX_MASK) >> getVertexStageShift<Bitmask>()) |
((val & FRAGMENT_MASK) >> getFragmentStageShift<Bitmask>());
val = ((val & VERTEX_MASK) >> fvkutils::getVertexStageShift<Bitmask>()) |
((val & FRAGMENT_MASK) >> fvkutils::getFragmentStageShift<Bitmask>());
return (uint8_t) Bitmask(val).count();
}
@@ -67,10 +68,10 @@ struct VulkanDescriptorSetLayout : public HwDescriptorSetLayout, fvkmemory::Reso
// The bitmask representation of a set layout.
struct Bitmask {
// TODO: better utiltize the space below and use bitset instead.
UniformBufferBitmask ubo; // 8 bytes
UniformBufferBitmask dynamicUbo; // 8 bytes
SamplerBitmask sampler; // 8 bytes
InputAttachmentBitmask inputAttachment; // 8 bytes
fvkutils::UniformBufferBitmask ubo; // 8 bytes
fvkutils::UniformBufferBitmask dynamicUbo; // 8 bytes
fvkutils::SamplerBitmask sampler; // 8 bytes
fvkutils::InputAttachmentBitmask inputAttachment; // 8 bytes
bool operator==(Bitmask const& right) const {
return ubo == right.ubo && dynamicUbo == right.dynamicUbo && sampler == right.sampler &&
@@ -138,7 +139,7 @@ public:
using OnRecycle = std::function<void(VulkanDescriptorSet*)>;
VulkanDescriptorSet(VkDescriptorSet rawSet,
UniformBufferBitmask const& dynamicUboMask,
fvkutils::UniformBufferBitmask const& dynamicUboMask,
uint8_t uniqueDynamicUboCount,
OnRecycle&& onRecycleFn)
: vkSet(rawSet),
@@ -164,7 +165,7 @@ public:
void acquire(fvkmemory::resource_ptr<VulkanBufferObject> buffer);
VkDescriptorSet const vkSet;
UniformBufferBitmask const dynamicUboMask;
fvkutils::UniformBufferBitmask const dynamicUboMask;
uint8_t const uniqueDynamicUboCount;
private:
@@ -193,7 +194,7 @@ private:
};
struct VulkanProgram : public HwProgram, fvkmemory::Resource {
using BindingList = CappedArray<uint16_t, MAX_SAMPLER_COUNT>;
using BindingList = fvkutils::StaticVector<uint16_t, MAX_SAMPLER_COUNT>;
VulkanProgram(VkDevice device, Program const& builder) noexcept;
~VulkanProgram();
@@ -16,6 +16,7 @@
#include <bluevk/BlueVK.h> // must be included before vk_mem_alloc
#if defined(__clang__)
#pragma clang diagnostic push
// Needed because not all clang versions have the warning -Wdeprecated-copy.
@@ -32,6 +33,7 @@
#pragma clang diagnostic ignored "-Wextra-semi"
#pragma clang diagnostic ignored "-Wc++98-compat-extra-semi"
#pragma clang diagnostic ignored "-Wthread-safety-analysis"
#endif
static const PFN_vkGetInstanceProcAddr& vkGetInstanceProcAddr = bluevk::vkGetInstanceProcAddr;
static const PFN_vkGetDeviceProcAddr& vkGetDeviceProcAddr = bluevk::vkGetDeviceProcAddr;
@@ -39,4 +41,7 @@ static const PFN_vkGetDeviceProcAddr& vkGetDeviceProcAddr = bluevk::vkGetDeviceP
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
@@ -27,7 +27,9 @@
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#endif
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wc++98-compat-extra-semi"
#endif
#include "vk_mem_alloc.h"
@@ -24,12 +24,14 @@
#include "VulkanConstants.h"
#include "VulkanHandles.h"
#include "VulkanTexture.h"
#include "VulkanUtility.h"
#include "vulkan/utils/Conversion.h"
#if defined(__clang__)
// Vulkan functions often immediately dereference pointers, so it's fine to pass in a pointer
// to a stack-allocated variable.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-stack-address"
#endif
using namespace bluevk;
@@ -194,7 +196,7 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
vkDs.depthTestEnable = VK_TRUE;
vkDs.depthWriteEnable = raster.depthWriteEnable;
vkDs.depthCompareOp = getCompareOp(raster.depthCompareOp);
vkDs.depthCompareOp = fvkutils::getCompareOp(raster.depthCompareOp);
vkDs.depthBoundsTestEnable = VK_FALSE;
vkDs.stencilTestEnable = VK_FALSE;
vkDs.minDepthBounds = 0.0f;
@@ -323,4 +325,6 @@ bool VulkanPipelineCache::PipelineEqual::operator()(const PipelineKey& k1,
} // namespace filament::backend
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
@@ -19,7 +19,6 @@
#include "VulkanCommands.h"
#include "VulkanMemory.h"
#include "VulkanUtility.h"
#include <backend/DriverEnums.h>
#include <backend/TargetBufferInfo.h>
@@ -68,8 +67,10 @@ public:
VkSpecializationInfo* specializationInfos = nullptr;
};
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wpadded"
#endif
// The RasterState POD contains standard graphics-related state like blending, culling, etc.
// The following states are omitted because Filament never changes them:
@@ -212,7 +213,9 @@ private:
bool operator()(const PipelineKey& k1, const PipelineKey& k2) const;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
// CACHE ENTRY STRUCTS
// -------------------
@@ -19,8 +19,9 @@
#include "DataReshaper.h"
#include "VulkanCommands.h"
#include "VulkanHandles.h"
#include "VulkanImageUtility.h"
#include "VulkanTexture.h"
#include "vulkan/utils/Conversion.h" // getComponentType()
#include "vulkan/utils/Image.h"
#include <utils/Log.h>
@@ -218,7 +219,7 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
};
vkBeginCommandBuffer(cmdbuffer, &binfo);
imgutil::transitionLayout(cmdbuffer, {
fvkutils::transitionLayout(cmdbuffer, {
.image = stagingImage,
.oldLayout = VulkanLayout::UNDEFINED,
.newLayout = VulkanLayout::TRANSFER_DST,
@@ -265,8 +266,8 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
imageCopyRegion.srcOffset.y + imageCopyRegion.extent.height <= srcExtent.height);
vkCmdCopyImage(cmdbuffer, srcAttachment.getImage(),
imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC), stagingImage,
imgutil::getVkLayout(VulkanLayout::TRANSFER_DST), 1, &imageCopyRegion);
fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC), stagingImage,
fvkutils::getVkLayout(VulkanLayout::TRANSFER_DST), 1, &imageCopyRegion);
// Restore the source image layout.
srcTexture->transitionLayout(cmdbuffer, srcRange, srcTexture->getDefaultLayout());
@@ -318,8 +319,8 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
vkMapMemory(device, stagingMemory, 0, VK_WHOLE_SIZE, 0, (void**) &srcPixels);
srcPixels += subResourceLayout.offset;
if (!DataReshaper::reshapeImage(&p, getComponentType(srcFormat),
getComponentCount(srcFormat), srcPixels,
if (!DataReshaper::reshapeImage(&p, fvkutils::getComponentType(srcFormat),
fvkutils::getComponentCount(srcFormat), srcPixels,
static_cast<int>(subResourceLayout.rowPitch), static_cast<int>(width),
static_cast<int>(height), swizzle)) {
FVK_LOGE << "Unsupported PixelDataFormat or PixelDataType" << utils::io::endl;
@@ -15,6 +15,7 @@
*/
#include "vulkan/VulkanSamplerCache.h"
#include "vulkan/utils/Conversion.h"
#include <utils/Panic.h>
@@ -114,7 +115,7 @@ VkSampler VulkanSamplerCache::getSampler(SamplerParams params) noexcept {
.anisotropyEnable = params.anisotropyLog2 == 0 ? 0u : 1u,
.maxAnisotropy = (float)(1u << params.anisotropyLog2),
.compareEnable = getCompareEnable(params.compareMode),
.compareOp = getCompareOp(params.compareFunc),
.compareOp = fvkutils::getCompareOp(params.compareFunc),
.minLod = 0.0f,
.maxLod = getMaxLod(params.filterMin),
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
@@ -18,7 +18,6 @@
#define TNT_FILAMENT_BACKEND_VULKANSAMPLERCACHE_H
#include "VulkanContext.h"
#include "VulkanUtility.h"
#include <tsl/robin_map.h>
@@ -18,9 +18,9 @@
#include "VulkanCommands.h"
#include "VulkanConstants.h"
#include "VulkanImageUtility.h"
#include "VulkanMemory.h"
#include "VulkanUtility.h"
#include "vulkan/utils/Conversion.h"
#include "vulkan/utils/Image.h"
#include <utils/Panic.h>
@@ -72,7 +72,7 @@ VulkanStage const* VulkanStagePool::acquireStage(uint32_t numBytes) {
VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, PixelDataType type,
uint32_t width, uint32_t height) {
const VkFormat vkformat = getVkFormat(format, type);
const VkFormat vkformat = fvkutils::getVkFormat(format, type);
for (auto image : mFreeImages) {
if (image->format == vkformat && image->width == width && image->height == height) {
mFreeImages.erase(image);
@@ -113,7 +113,7 @@ VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, Pi
assert_invariant(result == VK_SUCCESS);
VkImageAspectFlags const aspectFlags = getImageAspect(vkformat);
VkImageAspectFlags const aspectFlags = fvkutils::getImageAspect(vkformat);
VkCommandBuffer const cmdbuffer = mCommands->get().buffer();
// We use VK_IMAGE_LAYOUT_GENERAL here because the spec says:
@@ -122,7 +122,7 @@ VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, Pi
// VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL layout. Calling
// vkGetImageSubresourceLayout for a linear image returns a subresource layout mapping that is
// valid for either of those image layouts."
imgutil::transitionLayout(cmdbuffer, {
fvkutils::transitionLayout(cmdbuffer, {
.image = image->image,
.oldLayout = VulkanLayout::UNDEFINED,
.newLayout = VulkanLayout::READ_WRITE, // (= VK_IMAGE_LAYOUT_GENERAL)
+25 -32
View File
@@ -17,8 +17,8 @@
#include "VulkanCommands.h"
#include "VulkanMemory.h"
#include "VulkanTexture.h"
#include "VulkanUtility.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Conversion.h"
#include <DataReshaper.h>
#include <backend/DriverEnums.h>
@@ -152,7 +152,7 @@ VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator,
bool isProtected)
: mVkFormat(format),
mViewType(viewType),
mFullViewRange{filament::backend::getImageAspect(format), 0, levels, 0, layerCount},
mFullViewRange{fvkutils::getImageAspect(format), 0, levels, 0, layerCount},
mDefaultLayout(defaultLayout),
mIsProtected(isProtected),
mStagePool(stagePool),
@@ -169,7 +169,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator,
: HwTexture(SamplerType::SAMPLER_2D, 1, samples, width, height, 1, TextureFormat::UNUSED,
tusage),
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
allocator, commands, stagePool, format, imgutil::getViewType(SamplerType::SAMPLER_2D),
allocator, commands, stagePool, format, fvkutils::getViewType(SamplerType::SAMPLER_2D),
1, 1, getDefaultLayoutImpl(tusage), any(usage & TextureUsage::PROTECTED))) {
mState->mTextureImage = image;
mState->mTextureImageMemory = memory;
@@ -183,9 +183,10 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
uint8_t levels, TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h,
uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool)
: HwTexture(target, levels, samples, w, h, depth, tformat, tusage),
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
allocator, commands, stagePool, backend::getVkFormat(tformat),
imgutil::getViewType(target), levels, getLayerCount(target, depth),
allocator, commands, stagePool, fvkutils::getVkFormat(tformat),
fvkutils::getViewType(target), levels, getLayerCount(target, depth),
VulkanLayout::UNDEFINED, any(usage & TextureUsage::PROTECTED))) {
// Create an appropriately-sized device-only VkImage, but do not fill it yet.
VkImageCreateInfo imageInfo{
@@ -198,20 +199,11 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = 0,
};
if (target == SamplerType::SAMPLER_3D && any(tusage & TextureUsage::ALL_ATTACHMENTS)) {
if (context.isImageView2DOn3DImageSupported()) {
// Note that VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT is only meant to create 2D views of
// a 3D image in the case where the image is the render target. So, for example, it's
// not meant to allow for 2D views that can be used with a sampler.
imageInfo.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
} else {
FVK_LOGW << "Note: creating 2D views on 3D image is not available on this platform. "
<< "i.e. we cannot render to slices of a 3D image" << utils::io::endl;
}
} else if (target == SamplerType::SAMPLER_CUBEMAP) {
if (target == SamplerType::SAMPLER_CUBEMAP) {
imageInfo.arrayLayers = 6;
imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
} else if (target == SamplerType::SAMPLER_2D_ARRAY) {
}
if (target == SamplerType::SAMPLER_2D_ARRAY) {
imageInfo.arrayLayers = depth;
imageInfo.extent.depth = 1;
// NOTE: We do not use VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT here because:
@@ -290,16 +282,17 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
// any kind of attachment (color or depth).
const auto& limits = context.getPhysicalDeviceLimits();
if (imageInfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
samples = reduceSampleCount(samples, isVkDepthFormat(mState->mVkFormat)
? limits.sampledImageDepthSampleCounts
: limits.sampledImageColorSampleCounts);
samples = fvkutils::reduceSampleCount(samples,
fvkutils::isVkDepthFormat(mState->mVkFormat)
? limits.sampledImageDepthSampleCounts
: limits.sampledImageColorSampleCounts);
}
if (imageInfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
samples = reduceSampleCount(samples, limits.framebufferColorSampleCounts);
samples = fvkutils::reduceSampleCount(samples, limits.framebufferColorSampleCounts);
}
if (imageInfo.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
samples = reduceSampleCount(samples, limits.sampledImageDepthSampleCounts);
samples = fvkutils::reduceSampleCount(samples, limits.sampledImageDepthSampleCounts);
}
this->samples = samples;
imageInfo.samples = (VkSampleCountFlagBits) samples;
@@ -410,8 +403,8 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
}
// If format conversion is both required and supported, use vkCmdBlitImage.
const VkFormat hostFormat = backend::getVkFormat(hostData->format, hostData->type);
const VkFormat deviceFormat = getVkFormatLinear(mState->mVkFormat);
const VkFormat hostFormat = fvkutils::getVkFormat(hostData->format, hostData->type);
const VkFormat deviceFormat = fvkutils::getVkFormatLinear(mState->mVkFormat);
if (hostFormat != deviceFormat && hostFormat != VK_FORMAT_UNDEFINED) {
assert_invariant(xoffset == 0 && yoffset == 0 && zoffset == 0 &&
"Offsets not yet supported when format conversion is required.");
@@ -470,7 +463,7 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
VulkanLayout const newLayout = VulkanLayout::TRANSFER_DST;
VulkanLayout nextLayout = getLayout(transitionRange.baseArrayLayer, miplevel);
VkImageLayout const newVkLayout = imgutil::getVkLayout(newLayout);
VkImageLayout const newVkLayout = fvkutils::getVkLayout(newLayout);
if (nextLayout == VulkanLayout::UNDEFINED) {
nextLayout = getDefaultLayout();
@@ -517,8 +510,8 @@ void VulkanTexture::updateImageWithBlit(const PixelBufferDescriptor& hostData, u
VulkanLayout const oldLayout = getLayout(layer, miplevel);
transitionLayout(&commands, range, newLayout);
vkCmdBlitImage(cmdbuf, stage->image, imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC),
mState->mTextureImage, imgutil::getVkLayout(newLayout), 1, blitRegions, VK_FILTER_NEAREST);
vkCmdBlitImage(cmdbuf, stage->image, fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC),
mState->mTextureImage, fvkutils::getVkLayout(newLayout), 1, blitRegions, VK_FILTER_NEAREST);
transitionLayout(&commands, range, oldLayout);
}
@@ -566,7 +559,7 @@ VkImageView VulkanTexture::getImageView(VkImageSubresourceRange range, VkImageVi
VkImageAspectFlags VulkanTexture::getImageAspect() const {
// Helper function in VulkanUtility
return filament::backend::getImageAspect(mState->mVkFormat);
return fvkutils::getImageAspect(mState->mVkFormat);
}
bool VulkanTexture::transitionLayout(VulkanCommandBuffer* commands,
@@ -609,7 +602,7 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR
if (layout == newLayout) {
continue;
}
hasTransitions = hasTransitions || imgutil::transitionLayout(cmdbuf, {
hasTransitions = hasTransitions || fvkutils::transitionLayout(cmdbuf, {
.image = mState->mTextureImage,
.oldLayout = layout,
.newLayout = newLayout,
@@ -624,7 +617,7 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR
}
}
} else if (newLayout != oldLayout) {
hasTransitions = imgutil::transitionLayout(cmdbuf, {
hasTransitions = fvkutils::transitionLayout(cmdbuf, {
.image = mState->mTextureImage,
.oldLayout = oldLayout,
.newLayout = newLayout,
@@ -659,7 +652,7 @@ void VulkanTexture::samplerToAttachmentBarrier(VulkanCommandBuffer* commands,
VkImageSubresourceRange const& range) {
VkCommandBuffer const cmdbuf = commands->buffer();
VkImageLayout const layout =
imgutil::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel));
fvkutils::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel));
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_SHADER_READ_BIT,
@@ -682,7 +675,7 @@ void VulkanTexture::attachmentToSamplerBarrier(VulkanCommandBuffer* commands,
VkImageSubresourceRange const& range) {
VkCommandBuffer const cmdbuf = commands->buffer();
VkImageLayout const layout
= imgutil::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel));
= fvkutils::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel));
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+1 -1
View File
@@ -20,9 +20,9 @@
#include "DriverBase.h"
#include "VulkanBuffer.h"
#include "VulkanImageUtility.h"
#include "vulkan/memory/Resource.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Image.h"
#include <utils/Hash.h>
#include <utils/RangeMap.h>
@@ -16,11 +16,10 @@
#include "VulkanDescriptorSetManager.h"
#include <vulkan/VulkanCommands.h>
#include <vulkan/VulkanHandles.h>
#include <vulkan/VulkanUtility.h>
#include <vulkan/VulkanConstants.h>
#include <vulkan/VulkanImageUtility.h>
#include "vulkan/VulkanCommands.h"
#include "vulkan/VulkanHandles.h"
#include "vulkan/VulkanConstants.h"
#include <utils/FixedCapacityVector.h>
#include <utils/Panic.h>
@@ -207,17 +206,17 @@ uint32_t createBindings(VkDescriptorSetLayoutBinding* toBind, uint32_t count, Vk
mask.forEachSetBit([&](size_t index) {
VkShaderStageFlags stages = 0;
uint32_t binding = 0;
if (index < getFragmentStageShift<Bitmask>()) {
if (index < fvkutils::getFragmentStageShift<Bitmask>()) {
binding = (uint32_t) index;
stages |= VK_SHADER_STAGE_VERTEX_BIT;
auto fragIndex = index + getFragmentStageShift<Bitmask>();
auto fragIndex = index + fvkutils::getFragmentStageShift<Bitmask>();
if (mask.test(fragIndex)) {
stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
alreadySeen.set(fragIndex);
}
} else if (!alreadySeen.test(index)) {
// We are in fragment stage bits
binding = (uint32_t) (index - getFragmentStageShift<Bitmask>());
binding = (uint32_t) (index - fvkutils::getFragmentStageShift<Bitmask>());
stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
}
@@ -346,7 +345,6 @@ private:
mVkLayouts;
};
VulkanDescriptorSetManager::VulkanDescriptorSetManager(VkDevice device,
fvkmemory::ResourceManager* resourceManager)
: mDevice(device),
@@ -376,10 +374,10 @@ void VulkanDescriptorSetManager::unbind(uint8_t setIndex) {
}
void VulkanDescriptorSetManager::commit(VulkanCommandBuffer* commands,
VkPipelineLayout pipelineLayout, DescriptorSetMask const& setMask) {
VkPipelineLayout pipelineLayout, fvkutils::DescriptorSetMask const& setMask) {
// setMask indicates the set of descriptor sets the driver wants to bind, curMask is the
// actual set of sets that *needs* to be bound.
DescriptorSetMask curMask = setMask;
fvkutils::DescriptorSetMask curMask = setMask;
auto& updateSets = mStashedSets;
auto& lastBoundSets = mLastBoundInfo.boundSets;
@@ -458,7 +456,7 @@ void VulkanDescriptorSetManager::updateSampler(fvkmemory::resource_ptr<VulkanDes
} else {
info.imageView = texture->getViewForType(range, expectedType);
}
info.imageLayout = imgutil::getVkLayout(texture->getDefaultLayout());
info.imageLayout = fvkutils::getVkLayout(texture->getDefaultLayout());
VkWriteDescriptorSet const descriptorWrite = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
@@ -18,9 +18,8 @@
#define TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETMANAGER_H
#include "vulkan/VulkanHandles.h"
#include "vulkan/VulkanTexture.h"
#include "vulkan/VulkanUtility.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Definitions.h" // For DescriptorSetMask
#include <backend/DriverEnums.h>
#include <backend/Program.h>
@@ -68,7 +67,7 @@ public:
void unbind(uint8_t setIndex);
void commit(VulkanCommandBuffer* commands, VkPipelineLayout pipelineLayout,
DescriptorSetMask const& setMask);
fvkutils::DescriptorSetMask const& setMask);
fvkmemory::resource_ptr<VulkanDescriptorSet> createSet(Handle<HwDescriptorSet> handle,
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout);
@@ -93,7 +92,7 @@ private:
struct {
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
DescriptorSetMask setMask;
fvkutils::DescriptorSetMask setMask;
DescriptorSetArray boundSets = {};
} mLastBoundInfo;
};
@@ -21,7 +21,7 @@
#include "vulkan/platform/VulkanPlatformSwapChainImpl.h"
#include "vulkan/VulkanConstants.h"
#include "vulkan/VulkanDriver.h"
#include "vulkan/VulkanUtility.h"
#include "vulkan/utils/Helper.h"
#include <bluevk/BlueVK.h>
#include <utils/PrivateImplementation-impl.h>
@@ -84,13 +84,6 @@ FixedCapacityVector<const char*> getEnabledLayers() {
}
#endif // FVK_EANBLED(FVK_DEBUG_VALIDATION)
template<typename StructA, typename StructB>
StructA* chainStruct(StructA* structA, StructB* structB) {
structB->pNext = const_cast<void*>(structA->pNext);
structA->pNext = (void*) structB;
return structA;
}
void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
// Print some driver or MoltenVK information if it is available.
if (vkGetPhysicalDeviceProperties2) {
@@ -99,8 +92,8 @@ void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
};
VkPhysicalDeviceProperties2 physicalDeviceProperties2 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
.pNext = &driverProperties,
};
chainStruct(&physicalDeviceProperties2, &driverProperties);
vkGetPhysicalDeviceProperties2(device, &physicalDeviceProperties2);
FVK_LOGI << "Vulkan device driver: " << driverProperties.driverName << " "
<< driverProperties.driverInfo << utils::io::endl;
@@ -133,7 +126,7 @@ void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
const int minor = VK_VERSION_MINOR(deviceProperties.apiVersion);
const FixedCapacityVector<VkPhysicalDevice> physicalDevices
= filament::backend::enumerate(vkEnumeratePhysicalDevices, instance);
= fvkutils::enumerate(vkEnumeratePhysicalDevices, instance);
FVK_LOGI << "Selected physical device '" << deviceProperties.deviceName << "' from "
<< physicalDevices.size() << " physical devices. "
@@ -179,7 +172,7 @@ ExtensionSet getInstanceExtensions(ExtensionSet const& externallyRequiredExts =
};
ExtensionSet exts;
FixedCapacityVector<VkExtensionProperties> const availableExts =
filament::backend::enumerate(vkEnumerateInstanceExtensionProperties,
fvkutils::enumerate(vkEnumerateInstanceExtensionProperties,
static_cast<char const*>(nullptr) /* pLayerName */);
for (auto const& extProps: availableExts) {
utils::CString name { extProps.extensionName };
@@ -201,7 +194,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
#endif
// We only support external image for Android for now, but nothing bars us from
// We only support external image for Android for now, but nothing bars us from
// supporting other platforms.
#if defined(__ANDROID__)
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
@@ -219,7 +212,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
ExtensionSet exts;
// Identify supported physical device extensions
FixedCapacityVector<VkExtensionProperties> const extensions
= filament::backend::enumerate(vkEnumerateDeviceExtensionProperties, device,
= fvkutils::enumerate(vkEnumerateDeviceExtensionProperties, device,
static_cast<const char*>(nullptr) /* pLayerName */);
for (auto const& extension: extensions) {
utils::CString name { extension.extensionName };
@@ -238,9 +231,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
VkInstance createInstance(ExtensionSet const& requiredExts) {
VkInstance instance;
VkInstanceCreateInfo instanceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
};
VkInstanceCreateInfo instanceCreateInfo = {};
bool validationFeaturesSupported = false;
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
@@ -291,6 +282,7 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
appInfo.pEngineName = "Filament";
appInfo.apiVersion
= VK_MAKE_API_VERSION(0, FVK_REQUIRED_VERSION_MAJOR, FVK_REQUIRED_VERSION_MINOR, 0);
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &appInfo;
instanceCreateInfo.enabledExtensionCount = enabledExtensionCount;
instanceCreateInfo.ppEnabledExtensionNames = ppEnabledExtensions;
@@ -298,17 +290,16 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
}
VkValidationFeaturesEXT features = {
.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
};
VkValidationFeaturesEXT features = {};
VkValidationFeatureEnableEXT enables[] = {
VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
};
if (validationFeaturesSupported) {
features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
features.enabledValidationFeatureCount = sizeof(enables) / sizeof(enables[0]);
features.pEnabledValidationFeatures = enables;
chainStruct(&instanceCreateInfo, &features);
instanceCreateInfo.pNext = &features;
}
VkResult result = vkCreateInstance(&instanceCreateInfo, VKALLOC, &instance);
@@ -319,13 +310,11 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
VkPhysicalDeviceFeatures2 const& features, uint32_t graphicsQueueFamilyIndex,
uint32_t protectedGraphicsQueueFamilyIndex, ExtensionSet const& deviceExtensions,
bool requestImageView2DOn3DImage) {
uint32_t protectedGraphicsQueueFamilyIndex, ExtensionSet const& deviceExtensions) {
VkDevice device;
float queuePriority[] = {1.0f};
VkDeviceCreateInfo deviceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
};
VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
const float queuePriority[] = {1.0f};
VkDeviceCreateInfo deviceCreateInfo = {};
FixedCapacityVector<const char*> requestExtensions;
requestExtensions.reserve(deviceExtensions.size() + 1);
@@ -334,7 +323,6 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
for (auto const& ext: deviceExtensions) {
requestExtensions.push_back(ext.data());
}
VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
deviceQueueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
deviceQueueCreateInfo[0].queueFamilyIndex = graphicsQueueFamilyIndex;
deviceQueueCreateInfo[0].queueCount = 1;
@@ -346,6 +334,7 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
deviceQueueCreateInfo[1].queueCount = 1;
deviceQueueCreateInfo[1].pQueuePriorities = &queuePriority[0];
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
bool const hasProtectedQueue = protectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX;
deviceCreateInfo.queueCreateInfoCount = hasProtectedQueue ? 2 : 1;
deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo;
@@ -364,36 +353,42 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
deviceCreateInfo.enabledExtensionCount = (uint32_t) requestExtensions.size();
deviceCreateInfo.ppEnabledExtensionNames = requestExtensions.data();
void* pNext = nullptr;
VkPhysicalDevicePortabilitySubsetFeaturesKHR portability = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
.imageViewFormatSwizzle = VK_TRUE,
.mutableComparisonSamplers = VK_TRUE,
.imageView2DOn3DImage = requestImageView2DOn3DImage ? VK_TRUE : VK_FALSE,
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
.pNext = nullptr,
.imageViewFormatSwizzle = VK_TRUE,
.mutableComparisonSamplers = VK_TRUE,
};
if (setContains(deviceExtensions, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
chainStruct(&deviceCreateInfo, &portability);
portability.pNext = pNext;
pNext = &portability;
}
VkPhysicalDeviceMultiviewFeaturesKHR multiview = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
.pNext = nullptr,
.multiview = VK_TRUE,
.multiviewGeometryShader = VK_FALSE,
.multiviewTessellationShader = VK_FALSE,
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
.pNext = nullptr,
.multiview = VK_TRUE,
.multiviewGeometryShader = VK_FALSE,
.multiviewTessellationShader = VK_FALSE
};
if (setContains(deviceExtensions, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
chainStruct(&deviceCreateInfo, &multiview);
multiview.pNext = pNext;
pNext = &multiview;
}
VkPhysicalDeviceProtectedMemoryFeatures protectedMemory = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
.protectedMemory = VK_TRUE,
};
if (hasProtectedQueue) {
// Enable protected memory, if requested.
chainStruct(&deviceCreateInfo, &protectedMemory);
protectedMemory.protectedMemory = VK_TRUE;
protectedMemory.pNext = pNext;
pNext = &protectedMemory;
}
deviceCreateInfo.pNext = pNext;
VkResult result = vkCreateDevice(physicalDevice, &deviceCreateInfo, VKALLOC, &device);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
<< "vkCreateDevice error=" << static_cast<int32_t>(result);
@@ -478,7 +473,7 @@ inline int deviceTypeOrder(VkPhysicalDeviceType deviceType) {
VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
VulkanPlatform::Customization::GPUPreference const& gpuPreference) {
FixedCapacityVector<VkPhysicalDevice> const physicalDevices =
filament::backend::enumerate(vkEnumeratePhysicalDevices, instance);
fvkutils::enumerate(vkEnumeratePhysicalDevices, instance);
struct DeviceInfo {
VkPhysicalDevice device = VK_NULL_HANDLE;
VkPhysicalDeviceType deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
@@ -506,14 +501,14 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
// Does the device have any command queues that support graphics?
// In theory, we should also ensure that the device supports presentation of our
// particular VkSurface, but we don't have a VkSurface yet, so we'll skip this requirement.
if (identifyGraphicsQueueFamilyIndex(candidateDevice, VK_QUEUE_GRAPHICS_BIT)
if (identifyGraphicsQueueFamilyIndex(candidateDevice, VK_QUEUE_GRAPHICS_BIT)
== INVALID_VK_INDEX) {
continue;
}
// Does the device support the VK_KHR_swapchain extension?
FixedCapacityVector<VkExtensionProperties> const extensions
= filament::backend::enumerate(vkEnumerateDeviceExtensionProperties,
= fvkutils::enumerate(vkEnumerateDeviceExtensionProperties,
candidateDevice, static_cast<char const*>(nullptr) /* pLayerName */);
bool supportsSwapchain = false;
for (auto const& extension: extensions) {
@@ -565,7 +560,7 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
return device;
}
VkFormatList findAttachmentDepthStencilFormats(VkPhysicalDevice device) {
fvkutils::VkFormatList findAttachmentDepthStencilFormats(VkPhysicalDevice device) {
VkFormatFeatureFlags const features = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
// The ordering here indicates the preference of choosing depth+stencil format.
@@ -584,17 +579,17 @@ VkFormatList findAttachmentDepthStencilFormats(VkPhysicalDevice device) {
selectedFormats.push_back(format);
}
}
VkFormatList ret(selectedFormats.size());
fvkutils::VkFormatList ret(selectedFormats.size());
std::copy(selectedFormats.begin(), selectedFormats.end(), ret.begin());
return ret;
}
VkFormatList findBlittableDepthStencilFormats(VkPhysicalDevice device) {
fvkutils::VkFormatList findBlittableDepthStencilFormats(VkPhysicalDevice device) {
std::vector<VkFormat> selectedFormats;
VkFormatFeatureFlags const required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
for (VkFormat format : ALL_VK_FORMATS) {
if (isVkDepthFormat(format)) {
for (VkFormat format : fvkutils::ALL_VK_FORMATS) {
if (fvkutils::isVkDepthFormat(format)) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(device, format, &props);
if ((props.optimalTilingFeatures & required) == required) {
@@ -602,7 +597,7 @@ VkFormatList findBlittableDepthStencilFormats(VkPhysicalDevice device) {
}
}
}
VkFormatList ret(selectedFormats.size());
fvkutils::VkFormatList ret(selectedFormats.size());
std::copy(selectedFormats.begin(), selectedFormats.end(), ret.begin());
return ret;
}
@@ -726,11 +721,14 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
VkPhysicalDeviceProtectedMemoryFeatures queryProtectedMemoryFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
};
// Chain to the pNext linked list
queryProtectedMemoryFeatures.pNext = context.mPhysicalDeviceFeatures.pNext;
context.mPhysicalDeviceFeatures.pNext = &queryProtectedMemoryFeatures;
VkPhysicalDeviceProtectedMemoryProperties protectedMemoryProperties = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
};
chainStruct(&context.mPhysicalDeviceFeatures, &queryProtectedMemoryFeatures);
chainStruct(&context.mPhysicalDeviceProperties, &protectedMemoryProperties);
protectedMemoryProperties.pNext = context.mPhysicalDeviceProperties.pNext;
context.mPhysicalDeviceProperties.pNext = &protectedMemoryProperties;
// Initialize the following fields: physicalDeviceProperties, memoryProperties,
// physicalDeviceFeatures, graphicsQueueFamilyIndex.
@@ -740,17 +738,17 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
mImpl->mGraphicsQueueFamilyIndex
= mImpl->mGraphicsQueueFamilyIndex == INVALID_VK_INDEX
? identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
? identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
VK_QUEUE_GRAPHICS_BIT)
: mImpl->mGraphicsQueueFamilyIndex;
assert_invariant(mImpl->mGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
// We know we need to allocate the protected version of the VK objects
context.mProtectedMemorySupported =
context.mProtectedMemorySupported =
static_cast<bool>(queryProtectedMemoryFeatures.protectedMemory);
if (context.mProtectedMemorySupported) {
mImpl->mProtectedGraphicsQueueFamilyIndex
= identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
= identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_PROTECTED_BIT));
assert_invariant(mImpl->mProtectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
}
@@ -770,7 +768,7 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
// Applying the same logic to the protected queue index (Not sure about shared context and protection)
mImpl->mProtectedGraphicsQueueIndex
= mImpl->mProtectedGraphicsQueueIndex == INVALID_VK_INDEX ? 0 :
= mImpl->mProtectedGraphicsQueueIndex == INVALID_VK_INDEX ? 0 :
mImpl->mProtectedGraphicsQueueIndex;
ExtensionSet deviceExts;
@@ -787,24 +785,11 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
}
}
bool requestPortabilitySubsetImageView2DOn3DImage = false;
if (setContains(deviceExts, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
// We are on a non-conformant vulkan implementation so we need to ascertain if the features
// we need are available.
chainStruct(&context.mPhysicalDeviceFeatures, &context.mPortabilitySubsetFeatures);
vkGetPhysicalDeviceFeatures2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceFeatures);
requestPortabilitySubsetImageView2DOn3DImage =
context.mPortabilitySubsetFeatures.imageView2DOn3DImage == VK_TRUE;
}
mImpl->mDevice =
mImpl->mDevice == VK_NULL_HANDLE
? createLogicalDevice(mImpl->mPhysicalDevice, context.mPhysicalDeviceFeatures,
mImpl->mGraphicsQueueFamilyIndex,
mImpl->mProtectedGraphicsQueueFamilyIndex, deviceExts,
requestPortabilitySubsetImageView2DOn3DImage)
: mImpl->mDevice;
mImpl->mDevice
= mImpl->mDevice == VK_NULL_HANDLE ? createLogicalDevice(mImpl->mPhysicalDevice,
context.mPhysicalDeviceFeatures, mImpl->mGraphicsQueueFamilyIndex,
mImpl->mProtectedGraphicsQueueFamilyIndex, deviceExts)
: mImpl->mDevice;
assert_invariant(mImpl->mDevice != VK_NULL_HANDLE);
vkGetDeviceQueue(mImpl->mDevice, mImpl->mGraphicsQueueFamilyIndex, mImpl->mGraphicsQueueIndex,
@@ -199,7 +199,6 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataIm
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
<< "vkGetAndroidHardwareBufferProperties failed with error="
<< static_cast<int32_t>(result);
FILAMENT_CHECK_POSTCONDITION(metadata.format == formatInfo.format)
<< "mismatched image format for external image (AHB)";
metadata.externalFormat = formatInfo.externalFormat;
@@ -17,7 +17,9 @@
#include "VulkanPlatformSwapChainImpl.h"
#include "vulkan/VulkanConstants.h"
#include "vulkan/VulkanUtility.h"
#include "vulkan/utils/Definitions.h"
#include "vulkan/utils/Helper.h"
#include "vulkan/utils/Image.h"
#include <backend/DriverEnums.h>
@@ -29,9 +31,8 @@ namespace filament::backend {
namespace {
std::tuple<VkImage, VkDeviceMemory> createImageAndMemory(VulkanContext const& context,
VkDevice device, VkExtent2D extent, VkFormat format,
bool isProtected) {
bool const isDepth = isVkDepthFormat(format);
VkDevice device, VkExtent2D extent, VkFormat format, bool isProtected) {
bool const isDepth = fvkutils::isVkDepthFormat(format);
// Filament expects blit() to work with any texture, so we almost always set these usage flags
// (see copyFrame() and readPixels()).
VkImageUsageFlags const blittable =
@@ -83,9 +84,9 @@ std::tuple<VkImage, VkDeviceMemory> createImageAndMemory(VulkanContext const& co
return std::tuple(image, imageMemory);
}
VkFormat selectDepthFormat(VkFormatList const& depthFormats, bool hasStencil) {
VkFormat selectDepthFormat(fvkutils::VkFormatList const& depthFormats, bool hasStencil) {
auto const formatItr = std::find_if(depthFormats.begin(), depthFormats.end(),
hasStencil ? isVkStencilFormat : isVkDepthFormat);
hasStencil ? fvkutils::isVkStencilFormat : fvkutils::isVkDepthFormat);
assert_invariant(
formatItr != depthFormats.end() && "Cannot find suitable swapchain depth format");
return *formatItr;
@@ -169,7 +170,7 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
// Find a suitable surface format.
FixedCapacityVector<VkSurfaceFormatKHR> const surfaceFormats
= enumerate(vkGetPhysicalDeviceSurfaceFormatsKHR, mPhysicalDevice, mSurface);
= fvkutils::enumerate(vkGetPhysicalDeviceSurfaceFormatsKHR, mPhysicalDevice, mSurface);
std::array<VkFormat, 2> expectedFormats = {
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_B8G8R8A8_UNORM,
@@ -193,8 +194,8 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
// Verify that our chosen present mode is supported. In practice all devices support the FIFO
// mode, but we check for it anyway for completeness. (and to avoid validation warnings)
VkPresentModeKHR const desiredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
FixedCapacityVector<VkPresentModeKHR> presentModes
= enumerate(vkGetPhysicalDeviceSurfacePresentModesKHR, mPhysicalDevice, mSurface);
FixedCapacityVector<VkPresentModeKHR> presentModes = fvkutils::enumerate(
vkGetPhysicalDeviceSurfacePresentModesKHR, mPhysicalDevice, mSurface);
bool foundSuitablePresentMode = false;
for (VkPresentModeKHR mode: presentModes) {
if (mode == desiredPresentMode) {
@@ -251,7 +252,7 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "vkCreateSwapchainKHR failed."
<< " error=" << static_cast<int32_t>(result);
mSwapChainBundle.colors = enumerate(vkGetSwapchainImagesKHR, mDevice, mSwapchain);
mSwapChainBundle.colors = fvkutils::enumerate(vkGetSwapchainImagesKHR, mDevice, mSwapchain);
mSwapChainBundle.colorFormat = surfaceFormat.format;
mSwapChainBundle.depthFormat =
selectDepthFormat(mContext.getAttachmentDepthStencilFormats(), mHasStencil);
@@ -329,7 +330,7 @@ bool VulkanPlatformSurfaceSwapChain::hasResized() {
|| perceivedExtent.height == VULKAN_UNDEFINED_EXTENT) {
perceivedExtent = mFallbackExtent;
}
return !equivalent(mSwapChainBundle.extent, perceivedExtent);
return !fvkutils::equivalent(mSwapChainBundle.extent, perceivedExtent);
}
bool VulkanPlatformSurfaceSwapChain::isProtected() {
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,13 @@
* limitations under the License.
*/
#include "VulkanUtility.h"
#include "vulkan/utils/Conversion.h"
#include <utils/algorithm.h>
#include <utils/debug.h>
#include <utils/Panic.h>
#include "private/backend/BackendUtils.h"
using namespace bluevk;
namespace filament::backend {
namespace filament::backend::fvkutils {
VkFormat getVkFormat(ElementType type, bool normalized, bool integer) {
using ElementType = ElementType;
@@ -235,12 +231,6 @@ VkFormat getVkFormat(TextureFormat format) {
}
}
// Converts PixelBufferDescriptor format + type pair into a VkFormat.
//
// NOTE: This function only returns formats that support VK_FORMAT_FEATURE_BLIT_SRC_BIT as per
// "Required Format Support" in the Vulkan specification. These are the only formats that can be
// used for format conversion. If the requested format does not support this feature, then
// VK_FORMAT_UNDEFINED is returned.
VkFormat getVkFormat(PixelDataFormat format, PixelDataType type) {
if (type == PixelDataType::USHORT_565) return VK_FORMAT_R5G6B5_UNORM_PACK16;
if (type == PixelDataType::UINT_2_10_10_10_REV) return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
@@ -284,10 +274,6 @@ VkFormat getVkFormat(PixelDataFormat format, PixelDataType type) {
return VK_FORMAT_UNDEFINED;
}
// Converts an SRGB Vulkan format identifier into its corresponding canonical UNORM format. If the
// given format is not an SRGB format, it is returned unmodified. This function is useful when
// determining if blit-based conversion is needed, since SRGB is orthogonal to the actual bit layout
// of color components.
VkFormat getVkFormatLinear(VkFormat format) {
switch (format) {
case VK_FORMAT_R8_SRGB: return VK_FORMAT_R8_UNORM;
@@ -328,8 +314,6 @@ VkFormat getVkFormatLinear(VkFormat format) {
return format;
}
// See also FTexture::computeTextureDataSize, which takes a public-facing Texture format rather
// than a driver-level Texture format, and can account for a specified byte alignment.
uint32_t getBytesPerPixel(TextureFormat format) {
return (uint32_t) getFormatSize(format);
}
@@ -611,48 +595,4 @@ VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags) {
return flags;
}
bool equivalent(const VkRect2D& a, const VkRect2D& b) {
// These are all integers so there's no need for an epsilon.
return a.extent.width == b.extent.width && a.extent.height == b.extent.height &&
a.offset.x == b.offset.x && a.offset.y == b.offset.y;
}
bool equivalent(const VkExtent2D& a, const VkExtent2D& b) {
return a.height == b.height && a.width == b.width;
}
VkImageAspectFlags getImageAspect(VkFormat format) {
switch (format) {
case VK_FORMAT_D16_UNORM_S8_UINT:
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_X8_D24_UNORM_PACK32:
case VK_FORMAT_D32_SFLOAT:
return VK_IMAGE_ASPECT_DEPTH_BIT;
case VK_FORMAT_S8_UINT:
return VK_IMAGE_ASPECT_STENCIL_BIT;
default:
return VK_IMAGE_ASPECT_COLOR_BIT;
}
}
bool isVkDepthFormat(VkFormat format) {
return (getImageAspect(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
}
bool isVkStencilFormat(VkFormat format) {
return (getImageAspect(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
}
static uint32_t mostSignificantBit(uint32_t x) { return 1ul << (31ul - utils::clz(x)); }
uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask) {
if (sampleCount & mask) {
return sampleCount;
}
return mostSignificantBit((sampleCount - 1) & mask);
}
} // namespace filament::backend
} // namespace filament::backend::fvkutils
@@ -0,0 +1,76 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_CONVERSION_H
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_CONVERSION_H
#include <backend/DriverEnums.h>
#include <private/backend/BackendUtils.h> // for getFormatSize()
#include <bluevk/BlueVK.h>
// Methods for converting Filament types to Vulkan types
namespace filament::backend::fvkutils {
VkFormat getVkFormat(ElementType type, bool normalized, bool integer);
VkFormat getVkFormat(TextureFormat format);
// Converts PixelBufferDescriptor format + type pair into a VkFormat.
// NOTE: This function only returns formats that support VK_FORMAT_FEATURE_BLIT_SRC_BIT as per
// "Required Format Support" in the Vulkan specification. These are the only formats that can be
// used for format conversion. If the requested format does not support this feature, then
// VK_FORMAT_UNDEFINED is returned.
VkFormat getVkFormat(PixelDataFormat format, PixelDataType type);
// Converts an SRGB Vulkan format identifier into its corresponding canonical UNORM format. If the
// given format is not an SRGB format, it is returned unmodified. This function is useful when
// determining if blit-based conversion is needed, since SRGB is orthogonal to the actual bit layout
// of color components.
VkFormat getVkFormatLinear(VkFormat format);
// See also FTexture::computeTextureDataSize, which takes a public-facing Texture format rather
// than a driver-level Texture format, and can account for a specified byte alignment.
uint32_t getBytesPerPixel(TextureFormat format);
VkCompareOp getCompareOp(SamplerCompareFunc func);
VkBlendFactor getBlendFactor(BlendFunction mode);
VkCullModeFlags getCullMode(CullingMode mode);
VkFrontFace getFrontFace(bool inverseFrontFaces);
PixelDataType getComponentType(VkFormat format);
uint32_t getComponentCount(VkFormat format);
VkComponentMapping getSwizzleMap(TextureSwizzle const swizzle[4]);
VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags);
inline VkImageViewType getViewType(SamplerType target) {
switch (target) {
case SamplerType::SAMPLER_CUBEMAP:
return VK_IMAGE_VIEW_TYPE_CUBE;
case SamplerType::SAMPLER_2D_ARRAY:
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
case SamplerType::SAMPLER_3D:
return VK_IMAGE_VIEW_TYPE_3D;
default:
return VK_IMAGE_VIEW_TYPE_2D;
}
}
}// namespace filament::backend::fvkutils
#endif// TNT_FILAMENT_BACKEND_VULKAN_UTILS_CONVERSION_H
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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
*
@@ -14,82 +14,17 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_VULKANUTILITY_H
#define TNT_FILAMENT_BACKEND_VULKANUTILITY_H
#include <backend/DriverEnums.h>
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_DEFINITIONS_H
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_DEFINITIONS_H
#include <utils/bitset.h>
#include <utils/FixedCapacityVector.h>
#include <bluevk/BlueVK.h>
#include <utility>
// Definitions for common types used across classes.
namespace filament::backend {
VkFormat getVkFormat(ElementType type, bool normalized, bool integer);
VkFormat getVkFormat(TextureFormat format);
VkFormat getVkFormat(PixelDataFormat format, PixelDataType type);
VkFormat getVkFormatLinear(VkFormat format);
uint32_t getBytesPerPixel(TextureFormat format);
VkCompareOp getCompareOp(SamplerCompareFunc func);
VkBlendFactor getBlendFactor(BlendFunction mode);
VkCullModeFlags getCullMode(CullingMode mode);
VkFrontFace getFrontFace(bool inverseFrontFaces);
PixelDataType getComponentType(VkFormat format);
uint32_t getComponentCount(VkFormat format);
VkComponentMapping getSwizzleMap(TextureSwizzle const swizzle[4]);
VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags);
bool equivalent(const VkRect2D& a, const VkRect2D& b);
bool equivalent(const VkExtent2D& a, const VkExtent2D& b);
bool isVkDepthFormat(VkFormat format);
bool isVkStencilFormat(VkFormat format);
VkImageAspectFlags getImageAspect(VkFormat format);
uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask);
// Helper function for the vkEnumerateX methods. These methods have the format of
// VkResult vkEnumerateX(InputType1 arg1, InputTyp2 arg2, ..., uint32_t* size,
// OutputType* output_arg)
// Instead of macros and explicitly listing the template params, Variadic Template was also
// considered, but because the "variadic" part of the vk methods (i.e. the inputs) are before the
// non-variadic parts, this breaks the template type matching logic. Hence, we use a macro approach
// here.
#define EXPAND_ENUM(...) \
uint32_t size = 0; \
VkResult result = func(__VA_ARGS__, nullptr); \
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "enumerate size error"; \
utils::FixedCapacityVector<OutType> ret(size); \
result = func(__VA_ARGS__, ret.data()); \
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "enumerate error"; \
return std::move(ret);
#define EXPAND_ENUM_NO_ARGS() EXPAND_ENUM(&size)
#define EXPAND_ENUM_ARGS(...) EXPAND_ENUM(__VA_ARGS__, &size)
template <typename OutType>
utils::FixedCapacityVector<OutType> enumerate(VKAPI_ATTR VkResult (*func)(uint32_t*, OutType*)) {
EXPAND_ENUM_NO_ARGS();
}
template <typename InType, typename OutType>
utils::FixedCapacityVector<OutType> enumerate(
VKAPI_ATTR VkResult (*func)(InType, uint32_t*, OutType*), InType inData) {
EXPAND_ENUM_ARGS(inData);
}
template <typename InTypeA, typename InTypeB, typename OutType>
utils::FixedCapacityVector<OutType> enumerate(
VKAPI_ATTR VkResult (*func)(InTypeA, InTypeB, uint32_t*, OutType*), InTypeA inDataA,
InTypeB inDataB) {
EXPAND_ENUM_ARGS(inDataA, inDataB);
}
#undef EXPAND_ENUM
#undef EXPAND_ENUM_NO_ARGS
#undef EXPAND_ENUM_ARGS
namespace filament::backend::fvkutils {
// Useful shorthands
using VkFormatList = utils::FixedCapacityVector<VkFormat>;
@@ -406,128 +341,6 @@ constexpr VkFormat ALL_VK_FORMATS[] = {
VK_FORMAT_R16G16_S10_5_NV,
};
// An Array that will be statically fixed in capacity, but the "size" (as in user added elements) is
// variable. Note that this class is movable.
template<typename T, uint16_t CAPACITY>
class CappedArray {
private:
using FixedSizeArray = std::array<T, CAPACITY>;
public:
using const_iterator = typename FixedSizeArray::const_iterator;
using iterator = typename FixedSizeArray::iterator;
CappedArray() = default;
// Delete copy constructor/assignment.
CappedArray(CappedArray const& rhs) = delete;
CappedArray& operator=(CappedArray& rhs) = delete;
CappedArray(CappedArray&& rhs) noexcept {
this->swap(rhs);
}
CappedArray& operator=(CappedArray&& rhs) noexcept {
this->swap(rhs);
return *this;
}
inline ~CappedArray() {
clear();
}
inline const_iterator begin() const {
if (mInd == 0) {
return mArray.cend();
}
return mArray.cbegin();
}
inline const_iterator end() const {
if (mInd > 0 && mInd < CAPACITY) {
return mArray.begin() + mInd;
}
return mArray.cend();
}
inline iterator begin() {
if (mInd == 0) {
return mArray.end();
}
return mArray.begin();
}
inline iterator end() {
if (mInd > 0 && mInd < CAPACITY) {
return mArray.begin() + mInd;
}
return mArray.end();
}
inline T back() {
assert_invariant(mInd > 0);
return *(mArray.begin() + mInd);
}
inline void pop_back() {
assert_invariant(mInd > 0);
mInd--;
}
inline const_iterator find(T item) {
return std::find(begin(), end(), item);
}
inline void insert(T item) {
assert_invariant(mInd < CAPACITY);
mArray[mInd++] = item;
}
inline void erase(T item) {
PANIC_PRECONDITION("CappedArray::erase should not be called");
}
inline void clear() {
if (mInd == 0) {
return;
}
mInd = 0;
}
inline T& operator[](uint16_t ind) {
return mArray[ind];
}
inline T const& operator[](uint16_t ind) const {
return mArray[ind];
}
inline uint32_t size() const {
return mInd;
}
T* data() {
return mArray.data();
}
T const* data() const {
return mArray.data();
}
bool operator==(CappedArray const& b) const {
return this->mArray == b.mArray;
}
private:
void swap(CappedArray& rhs) {
std::swap(mArray, rhs.mArray);
std::swap(mInd, rhs.mInd);
}
FixedSizeArray mArray;
uint32_t mInd = 0;
};
using UniformBufferBitmask = utils::bitset64;
using SamplerBitmask = utils::bitset64;
@@ -550,7 +363,6 @@ static constexpr uint8_t getFragmentStageShift() noexcept {
// We have at most 4 descriptor sets. This is to indicate which ones are active.
using DescriptorSetMask = utils::bitset8;
} // namespace filament::backend::fvkutils
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_VULKANUTILITY_H
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_DEFINITIONS_H
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_HELPER_H
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_HELPER_H
#include <backend/DriverEnums.h>
#include <utils/bitset.h>
#include <utils/FixedCapacityVector.h>
#include <bluevk/BlueVK.h>
#include <utility>
namespace filament::backend::fvkutils {
inline bool equivalent(const VkRect2D& a, const VkRect2D& b) {
// These are all integers so there's no need for an epsilon.
return a.extent.width == b.extent.width && a.extent.height == b.extent.height &&
a.offset.x == b.offset.x && a.offset.y == b.offset.y;
}
inline bool equivalent(const VkExtent2D& a, const VkExtent2D& b) {
return a.height == b.height && a.width == b.width;
}
// Helper function for the vkEnumerateX methods. These methods have the format of
// VkResult vkEnumerateX(InputType1 arg1, InputTyp2 arg2, ..., uint32_t* size,
// OutputType* output_arg)
// Instead of macros and explicitly listing the template params, Variadic Template was also
// considered, but because the "variadic" part of the vk methods (i.e. the inputs) are before the
// non-variadic parts, this breaks the template type matching logic. Hence, we use a macro approach
// here.
#define EXPAND_ENUM(...) \
uint32_t size = 0; \
VkResult result = func(__VA_ARGS__, nullptr); \
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "enumerate size error"; \
utils::FixedCapacityVector<OutType> ret(size); \
result = func(__VA_ARGS__, ret.data()); \
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "enumerate error"; \
return std::move(ret);
#define EXPAND_ENUM_NO_ARGS() EXPAND_ENUM(&size)
#define EXPAND_ENUM_ARGS(...) EXPAND_ENUM(__VA_ARGS__, &size)
template <typename OutType>
utils::FixedCapacityVector<OutType> enumerate(VKAPI_ATTR VkResult (*func)(uint32_t*, OutType*)) {
EXPAND_ENUM_NO_ARGS();
}
template <typename InType, typename OutType>
utils::FixedCapacityVector<OutType> enumerate(
VKAPI_ATTR VkResult (*func)(InType, uint32_t*, OutType*), InType inData) {
EXPAND_ENUM_ARGS(inData);
}
template <typename InTypeA, typename InTypeB, typename OutType>
utils::FixedCapacityVector<OutType> enumerate(
VKAPI_ATTR VkResult (*func)(InTypeA, InTypeB, uint32_t*, OutType*), InTypeA inDataA,
InTypeB inDataB) {
EXPAND_ENUM_ARGS(inDataA, inDataB);
}
#undef EXPAND_ENUM
#undef EXPAND_ENUM_NO_ARGS
#undef EXPAND_ENUM_ARGS
} // namespace filament::backend::fvkutils
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_HELPER_H
@@ -14,9 +14,9 @@
* limitations under the License.
*/
#include "VulkanImageUtility.h"
#include "vulkan/utils/Image.h"
#include "VulkanTexture.h"
#include "vulkan/VulkanTexture.h"
#include <utils/Panic.h>
#include <utils/algorithm.h>
@@ -26,7 +26,7 @@
using namespace bluevk;
namespace filament::backend::imgutil {
namespace filament::backend::fvkutils {
namespace {
@@ -159,7 +159,41 @@ bool transitionLayout(VkCommandBuffer cmdbuffer,
return true;
}
}// namespace filament::backend
VkImageAspectFlags getImageAspect(VkFormat format) {
switch (format) {
case VK_FORMAT_D16_UNORM_S8_UINT:
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_X8_D24_UNORM_PACK32:
case VK_FORMAT_D32_SFLOAT:
return VK_IMAGE_ASPECT_DEPTH_BIT;
case VK_FORMAT_S8_UINT:
return VK_IMAGE_ASPECT_STENCIL_BIT;
default:
return VK_IMAGE_ASPECT_COLOR_BIT;
}
}
bool isVkDepthFormat(VkFormat format) {
return (getImageAspect(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
}
bool isVkStencilFormat(VkFormat format) {
return (getImageAspect(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
}
static uint32_t mostSignificantBit(uint32_t x) { return 1ul << (31ul - utils::clz(x)); }
uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask) {
if (sampleCount & mask) {
return sampleCount;
}
return mostSignificantBit((sampleCount - 1) & mask);
}
} // namespace filament::backend::fvkutils
bool operator<(const VkImageSubresourceRange& a, const VkImageSubresourceRange& b) {
if (a.aspectMask < b.aspectMask) return true;
@@ -14,8 +14,8 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_VULKANIMAGEUTILITY_H
#define TNT_FILAMENT_BACKEND_VULKANIMAGEUTILITY_H
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_IMAGE_H
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_IMAGE_H
#include <backend/DriverEnums.h>
@@ -59,22 +59,7 @@ struct VulkanLayoutTransition {
VkImageSubresourceRange subresources;
};
namespace imgutil {
inline VkImageViewType getViewType(SamplerType target) {
switch (target) {
case SamplerType::SAMPLER_CUBEMAP:
return VK_IMAGE_VIEW_TYPE_CUBE;
case SamplerType::SAMPLER_2D_ARRAY:
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
case SamplerType::SAMPLER_3D:
return VK_IMAGE_VIEW_TYPE_3D;
default:
return VK_IMAGE_VIEW_TYPE_2D;
}
}
namespace fvkutils {
constexpr inline VkImageLayout getVkLayout(VulkanLayout layout) {
switch (layout) {
@@ -109,7 +94,15 @@ constexpr inline VkImageLayout getVkLayout(VulkanLayout layout) {
// no transition necessary).
bool transitionLayout(VkCommandBuffer cmdbuffer, VulkanLayoutTransition transition);
} // namespace imgutil
bool isVkDepthFormat(VkFormat format);
bool isVkStencilFormat(VkFormat format);
VkImageAspectFlags getImageAspect(VkFormat format);
uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask);
} // namespace fvkutils
} // namespace filament::backend
@@ -117,5 +110,4 @@ bool operator<(const VkImageSubresourceRange& a, const VkImageSubresourceRange&
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::VulkanLayout& layout);
#endif // TNT_FILAMENT_BACKEND_VULKANIMAGEUTILITY_H
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_IMAGE_H
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "VulkanSpirvUtils.h"
#include "vulkan/utils/Spirv.h"
#include <utils/compiler.h> // UTILS_UNUSED_IN_RELEASE, UTILS_FALLTHROUGH
#include <utils/debug.h> // assert_invariant
@@ -22,12 +22,11 @@
#include <spirv/unified1/spirv.hpp>
#include <unordered_map>
#include <variant>
#include <vector>
#include <cstring>
#include <unordered_map>
#include <vector>
namespace filament::backend {
namespace filament::backend::fvkutils {
namespace {
@@ -99,7 +98,7 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
uint32_t const* data = (uint32_t*) blob.data();
uint32_t* outputData = output.data();
std::memcpy(&outputData[0], &data[0], HEADER_SIZE * 4);
memcpy(&outputData[0], &data[0], HEADER_SIZE * 4);
size_t outputCursor = HEADER_SIZE;
for (uint32_t cursor = HEADER_SIZE, cursorEnd = dataSize; cursor < cursorEnd;) {
@@ -147,61 +146,4 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
output.resize(outputCursor);
}
std::tuple<uint32_t,uint32_t, uint32_t> getProgramBindings(Program::ShaderBlob const& blob) {
std::unordered_map<uint32_t, uint32_t> targetToSet, targetToBinding;
constexpr size_t HEADER_SIZE = 5;
size_t const dataSize = blob.size() / 4;
uint32_t const* data = (uint32_t*) blob.data();
for (uint32_t cursor = HEADER_SIZE, cursorEnd = dataSize; cursor < cursorEnd;) {
uint32_t const firstWord = data[cursor];
uint32_t const wordCount = firstWord >> 16;
uint32_t const op = firstWord & 0x0000FFFF;
switch(op) {
case spv::Op::OpDecorate: {
if (data[cursor + 2] == spv::Decoration::DecorationDescriptorSet) {
uint32_t const targetVar = data[cursor + 1];
uint32_t const setId = data[cursor + 3];
targetToSet[targetVar] = setId;
} else if (data[cursor + 2] == spv::Decoration::DecorationBinding) {
uint32_t const targetVar = data[cursor + 1];
uint32_t const binding = data[cursor + 3];
targetToBinding[targetVar] = binding;
}
break;
}
default:
break;
}
cursor += wordCount;
}
constexpr uint32_t UBO = 0;
constexpr uint32_t SAMPLER = 1;
constexpr uint32_t IATTACHMENT = 2;
uint32_t ubo = 0, sampler = 0, inputAttachment = 0;
for (auto const& [target, setId]: targetToSet) {
uint32_t const binding = targetToBinding[target];
assert_invariant(binding < 32);
switch(setId) {
case UBO:
ubo |= (1 << binding);
break;
case SAMPLER:
sampler |= (1 << binding);
break;
case IATTACHMENT:
inputAttachment |= (1 << binding);
break;
default:
PANIC_POSTCONDITION("unexpected %d", (int) setId);
}
}
return {ubo, sampler, inputAttachment};
}
} // namespace filament::backend
} // namespace filament::backend::fvkutils
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 The Android Open Source Project
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,8 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_VULKANSPIRVUTILS_H
#define TNT_FILAMENT_BACKEND_VULKANSPIRVUTILS_H
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_SPIRV_H
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_SPIRV_H
#include <backend/Program.h>
@@ -24,7 +24,7 @@
#include <tuple>
#include <vector>
namespace filament::backend {
namespace filament::backend::fvkutils {
using SpecConstantValue = Program::SpecializationConstant::Type;
@@ -44,8 +44,9 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
std::vector<uint32_t>& output);
// bindings for UBO, samplers, input attachment
std::tuple<uint32_t, uint32_t, uint32_t> getProgramBindings(Program::ShaderBlob const& blob);
// This is no longer needed after the descriptor set refactor, but the code is good for reference.
// std::tuple<uint32_t, uint32_t, uint32_t> getProgramBindings(Program::ShaderBlob const& blob);
} // namespace filament::backend
} // namespace filament::backend::fvkutils
#endif // TNT_FILAMENT_BACKEND_VULKANSPIRVUTILS_H
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_SPIRV_H
@@ -0,0 +1,134 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_STATICVECTOR_H
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_STATICVECTOR_H
// An Array that will be statically fixed in capacity, but the "size" (as in user added elements) is
// variable. Note that this class is movable.
#include <utils/Panic.h>
#include <array>
namespace filament::backend::fvkutils {
template<typename T, uint16_t CAPACITY>
class StaticVector {
private:
using FixedSizeArray = std::array<T, CAPACITY>;
static_assert(CAPACITY <= (1LL << (8 * sizeof(uint16_t))));
public:
using const_iterator = typename FixedSizeArray::const_iterator;
using iterator = typename FixedSizeArray::iterator;
StaticVector() = default;
// Delete copy constructor/assignment.
StaticVector(StaticVector const& rhs) = delete;
StaticVector& operator=(StaticVector& rhs) = delete;
StaticVector(StaticVector&& rhs) noexcept {
std::swap(mSize, rhs.mSize);
std::swap(mArray, rhs.mArray);
}
StaticVector& operator=(StaticVector&& rhs) noexcept {
std::swap(mSize, rhs.mSize);
std::swap(mArray, rhs.mArray);
return *this;
}
inline ~StaticVector() {
clear();
}
inline const_iterator begin() const {
return mArray.cbegin();
}
inline const_iterator end() const {
assert_invariant(mSize <= CAPACITY);
return mArray.begin() + mSize;
}
inline iterator begin() {
return mArray.begin();
}
inline iterator end() {
assert_invariant(mSize <= CAPACITY);
return mArray.begin() + mSize;
}
inline T back() {
assert_invariant(mSize > 0);
return *(mArray.begin() + mSize);
}
inline void pop_back() {
assert_invariant(mSize > 0);
mSize--;
}
inline const_iterator find(T item) {
return std::find(begin(), end(), item);
}
inline void push_back(T item) {
assert_invariant(mSize < CAPACITY);
mArray[mSize++] = item;
}
inline void clear() {
mSize = 0;
}
inline T& operator[](size_t index) {
assert_invariant(index < mSize);
return mArray[index];
}
inline T const& operator[](size_t index) const {
return mArray[index];
}
inline uint16_t size() const {
return mSize;
}
T* data() {
return mArray.data();
}
T const* data() const {
return mArray.data();
}
bool operator==(StaticVector const& b) const {
return this->mArray == b.mArray && this->mSize == b.mSize;
}
private:
FixedSizeArray mArray;
uint16_t mSize = 0;
};
} // namespace filament::backend::fvkutils
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_STATICVECTOR_H
+8
View File
@@ -40,12 +40,16 @@ void Culler::intersects(
float4 const * const UTILS_RESTRICT planes = frustum.mPlanes;
count = round(count);
#if defined(__clang__)
#pragma clang loop vectorize_width(FILAMENT_CULLER_VECTORIZE_HINT)
#endif
for (size_t i = 0; i < count; i++) {
int visible = ~0;
float4 const sphere(b[i]);
#if defined(__clang__)
#pragma clang loop unroll(full)
#endif
for (size_t j = 0; j < 6; j++) {
// clang doesn't seem to generate vector * scalar instructions, which leads
// to increased register pressure and stack spills
@@ -69,11 +73,15 @@ void Culler::intersects(
float4 const * UTILS_RESTRICT const planes = frustum.mPlanes;
count = round(count);
#if defined(__clang__)
#pragma clang loop vectorize_width(FILAMENT_CULLER_VECTORIZE_HINT)
#endif
for (size_t i = 0; i < count; i++) {
int visible = ~0;
#if defined(__clang__)
#pragma clang loop unroll(full)
#endif
for (size_t j = 0; j < 6; j++) {
// clang doesn't seem to generate vector * scalar instructions, which leads
// to increased register pressure and stack spills
+2
View File
@@ -395,7 +395,9 @@ bool Froxelizer::update() noexcept {
const float linearizer = std::log2(zLightFar / zLightNear) / float(std::max(1u, mFroxelCountZ - 1u));
// for a strange reason when, vectorizing this loop, clang does some math in double
// and generates conversions to float. not worth it for so little iterations.
#if defined(__clang__)
#pragma clang loop vectorize(disable) unroll(disable)
#endif
for (ssize_t i = 1, n = mFroxelCountZ; i <= n; i++) {
mDistancesZ[i] = zLightFar * std::exp2(float(i - n) * linearizer);
}
+1 -1
View File
@@ -2661,7 +2661,7 @@ void PostProcessManager::TaaJitterCamera(
// update projection matrix
inoutCameraInfo->projection[2].xy -= jitterInClipSpace;
// VERTEX_DOMAIN_DEVICE doesn't apply the projection, but it still needs this
// clip transform, so we apply it separately (see main.vs)
// clip transform, so we apply it separately (see surface_main.vs)
inoutCameraInfo->clipTransform.zw -= jitterInClipSpace;
}
+3 -3
View File
@@ -253,7 +253,7 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
// The model matrix below is in fact inverted to get the view matrix and passed to the
// shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric.
// (see depth_main.fs). Note that in the case of VSM, 'b' below is identity.
// (see surface_depth_main.fs). Note that in the case of VSM, 'b' below is identity.
mCamera->setModelMatrix(FCamera::rigidTransformInverse(highPrecisionMultiplyd(Mv, b)));
mCamera->setCustomProjection(mat4(Mn * F * WLMp), znear, zfar);
@@ -315,7 +315,7 @@ ShadowMap::ShaderParameters ShadowMap::updatePunctual(
// The model matrix below is in fact inverted to get the view matrix and passed to the
// shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric.
// (see depth_main.fs). Note that in the case of VSM, 'b' below is identity.
// (see surface_depth_main.fs). Note that in the case of VSM, 'b' below is identity.
mCamera->setModelMatrix(FCamera::rigidTransformInverse(highPrecisionMultiplyd(Mv, b)));
mCamera->setCustomProjection(highPrecisionMultiplyd(Mn, Mp), nearPlane, farPlane);
@@ -719,7 +719,7 @@ mat4f ShadowMap::computeVsmLightSpaceMatrix(const mat4f& lightSpacePcf,
// For VSM, we want to leave the z coordinate in linear light-space, normalized between [0, 1],
// i.e. remapping [near, far] to [0, 1].
// When sampling a VSM shadow map, the shader follows suit, and doesn't divide by w for the z
// coordinate. See shadowing.fs.
// coordinate. See surface_shadowing.fs.
// compute z' = -(Mv * position).z / (far - near) - (near / (far - near))
const float scale = 1.0f / (zfar - znear);
mat4f lightSpaceVsm{ lightSpacePcf };
+4
View File
@@ -399,8 +399,10 @@ float3 DisplayRangeToneMapper::operator()(float3 const c) const noexcept {
//------------------------------------------------------------------------------
struct GenericToneMapper::Options {
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow"
#endif
void setParameters(
float contrast,
float midGrayIn,
@@ -424,7 +426,9 @@ struct GenericToneMapper::Options {
inputScale = (a * b * (midGrayOut - 1.0f)) / c;
outputScale = midGrayOut * (a - b) / c;
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
float contrast;
float midGrayIn;
+14
View File
@@ -52,10 +52,14 @@ using namespace backend;
struct ColorGrading::BuilderDetails {
const ToneMapper* toneMapper = nullptr;
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
ToneMapping toneMapping = ToneMapping::ACES_LEGACY;
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
bool hasAdjustments = false;
@@ -268,8 +272,10 @@ ColorGrading::Builder& ColorGrading::Builder::outputColorSpace(
return *this;
}
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
ColorGrading* ColorGrading::Builder::build(Engine& engine) {
// We want to see if any of the default adjustment values have been modified
// We skip the tonemapping operator on purpose since we always want to apply it
@@ -309,7 +315,9 @@ ColorGrading* ColorGrading::Builder::build(Engine& engine) {
return colorGrading;
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
//------------------------------------------------------------------------------
// Exposure
@@ -585,8 +593,10 @@ static std::tuple<TextureFormat, PixelDataFormat, PixelDataType>
}
}
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
// The following functions exist to preserve backward compatibility with the
// `FILMIC` set via the deprecated `ToneMapping` API. Selecting `ToneMapping::FILMIC`
// forces post-processing to be performed in sRGB to guarantee that the inverse tone
@@ -612,7 +622,9 @@ static float3 selectColorGradingLuminance(ColorGrading::ToneMapping const toneMa
}
return LUMINANCE_Rec2020;
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
using ColorTransform = float3(*)(float3);
@@ -792,7 +804,9 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) {
// we use a vectorize width of 8 because, on ARMv8 it allows the compiler to write eight
// 32-bits results in one go.
const size_t count = (config.lutDimension * config.lutDimension) & ~0x7u; // tell the compiler that we're a multiple of 8
#if defined(__clang__)
#pragma clang loop vectorize_width(8)
#endif
for (size_t i = 0; i < count; ++i) {
float4 v{src[i]};
uint32_t pr = uint32_t(std::floor(v.x * 1023.0f + 0.5f));
+41 -22
View File
@@ -706,28 +706,6 @@ int FEngine::loop() {
}
}
#if FILAMENT_ENABLE_MATDBG
#ifdef __ANDROID__
const char* portString = "8081";
#else
const char* portString = getenv("FILAMENT_MATDBG_PORT");
#endif
if (portString != nullptr) {
const int port = atoi(portString);
debug.server = new matdbg::DebugServer(mBackend, port);
// Sometimes the server can fail to spin up (e.g. if the above port is already in use).
// When this occurs, carry onward, developers can look at civetweb.txt for details.
if (!debug.server->isReady()) {
delete debug.server;
debug.server = nullptr;
} else {
debug.server->setEditCallback(FMaterial::onEditCallback);
debug.server->setQueryCallback(FMaterial::onQueryCallback);
}
}
#endif
JobSystem::setThreadName("FEngine::loop");
JobSystem::setThreadPriority(JobSystem::Priority::DISPLAY);
@@ -749,6 +727,47 @@ int FEngine::loop() {
return 0;
}
#if FILAMENT_ENABLE_MATDBG
#ifdef __ANDROID__
const char* portString = "8081";
#else
const char* portString = getenv("FILAMENT_MATDBG_PORT");
#endif
if (portString != nullptr) {
const int port = atoi(portString);
debug.server = new matdbg::DebugServer(mBackend, mDriver->getShaderLanguage(), port);
// Sometimes the server can fail to spin up (e.g. if the above port is already in use).
// When this occurs, carry onward, developers can look at civetweb.txt for details.
if (!debug.server->isReady()) {
delete debug.server;
debug.server = nullptr;
} else {
debug.server->setEditCallback(FMaterial::onEditCallback);
debug.server->setQueryCallback(FMaterial::onQueryCallback);
}
}
#endif
#if FILAMENT_ENABLE_FGVIEWER
#ifdef __ANDROID__
const char* fgviewerPortString = "8085";
#else
const char* fgviewerPortString = getenv("FILAMENT_FGVIEWER_PORT");
#endif
if (fgviewerPortString != nullptr) {
const int fgviewerPort = atoi(fgviewerPortString);
debug.fgviewerServer = new fgviewer::DebugServer(fgviewerPort);
// Sometimes the server can fail to spin up (e.g. if the above port is already in use).
// When this occurs, carry onward, developers can look at civetweb.txt for details.
if (!debug.fgviewerServer->isReady()) {
delete debug.fgviewerServer;
debug.fgviewerServer = nullptr;
}
}
#endif
while (true) {
if (!execute()) {
break;
+16 -16
View File
@@ -88,6 +88,14 @@ using MaterialKey = uint32_t;
} // namespace filament::matdbg
#endif
#if FILAMENT_ENABLE_FGVIEWER
#include <fgviewer/DebugServer.h>
#else
namespace filament::fgviewer {
class DebugServer;
} // namespace filament::fgviewer
#endif
namespace filament {
class Renderer;
@@ -252,20 +260,12 @@ public:
// Return a vector of shader languages, in order of preference.
utils::FixedCapacityVector<backend::ShaderLanguage> getShaderLanguage() const noexcept {
switch (mBackend) {
case Backend::DEFAULT:
case Backend::NOOP:
default:
return { backend::ShaderLanguage::ESSL3 };
case Backend::OPENGL:
return { getDriver().getFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0
? backend::ShaderLanguage::ESSL1
: backend::ShaderLanguage::ESSL3 };
case Backend::VULKAN:
return { backend::ShaderLanguage::SPIRV };
return { getDriver().getShaderLanguage() };
case Backend::METAL:
const auto& lang = mConfig.preferredShaderLanguage;
if (lang == Config::ShaderLanguage::MSL) {
return { backend::ShaderLanguage::MSL, backend::ShaderLanguage::METAL_LIBRARY };
return { backend::ShaderLanguage::MSL, backend::ShaderLanguage::METAL_LIBRARY};
}
return { backend::ShaderLanguage::METAL_LIBRARY, backend::ShaderLanguage::MSL };
}
@@ -681,6 +681,7 @@ public:
bool combine_multiview_images = false;
} stereo;
matdbg::DebugServer* server = nullptr;
fgviewer::DebugServer* fgviewerServer = nullptr;
} debug;
struct {
@@ -689,9 +690,11 @@ public:
bool use_shadow_atlas = false;
} shadows;
struct {
// TODO: default the following two flags to true.
#ifndef NDEBUG
bool assert_material_instance_in_use = true;
#else
bool assert_material_instance_in_use = false;
bool assert_destroy_material_before_material_instance = false;
#endif
} debug;
} engine;
struct {
@@ -718,10 +721,7 @@ public:
&features.engine.shadows.use_shadow_atlas, false },
{ "features.engine.debug.assert_material_instance_in_use",
"Assert when a MaterialInstance is destroyed while it is in use by RenderableManager.",
&features.engine.debug.assert_material_instance_in_use, false },
{ "features.engine.debug.assert_destroy_material_before_material_instance",
"Assert when a Material is destroyed but its instances are still alive.",
&features.engine.debug.assert_destroy_material_before_material_instance, false },
&features.engine.debug.assert_material_instance_in_use, false }
}};
utils::Slice<const FeatureFlag> getFeatureFlags() const noexcept {
+3 -8
View File
@@ -383,14 +383,9 @@ void FMaterial::terminate(FEngine& engine) {
auto const& materialInstanceResourceList = engine.getMaterialInstanceResourceList();
auto pos = materialInstanceResourceList.find(this);
if (UTILS_LIKELY(pos != materialInstanceResourceList.cend())) {
if (engine.features.engine.debug.assert_destroy_material_before_material_instance) {
FILAMENT_CHECK_PRECONDITION(pos->second.empty())
<< "destroying material \"" << this->getName().c_str_safe() << "\" but "
<< pos->second.size() << " instances still alive.";
} else {
utils::slog.e << "destroying material \"" << this->getName().c_str_safe() << "\" but "
<< pos->second.size() << " instances still alive.";
}
FILAMENT_CHECK_PRECONDITION(pos->second.empty())
<< "destroying material \"" << this->getName().c_str_safe() << "\" but "
<< pos->second.size() << " instances still alive.";
}
+1 -1
View File
@@ -66,7 +66,7 @@ MorphTargetBuffer* MorphTargetBuffer::Builder::build(Engine& engine) {
// ------------------------------------------------------------------------------------------------
// This value is limited by ES3.0, ES3.0 only guarantees 2048.
// When you change this value, you must change MAX_MORPH_TARGET_BUFFER_WIDTH at getters.vs
// When you change this value, you must change MAX_MORPH_TARGET_BUFFER_WIDTH at surface_getters.vs
constexpr size_t MAX_MORPH_TARGET_BUFFER_WIDTH = 2048;
static inline size_t getWidth(size_t const vertexCount) noexcept {
+10 -6
View File
@@ -781,7 +781,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
cameraInfo.projection = highPrecisionMultiply(ts, cameraInfo.projection);
// VERTEX_DOMAIN_DEVICE doesn't apply the projection, but it still needs this
// clip transform, so we apply it separately (see main.vs)
// clip transform, so we apply it separately (see surface_main.vs)
cameraInfo.clipTransform = { ts[0][0], ts[1][1], ts[3].x, ts[3].y };
// adjust svp to the new, larger, rendering dimensions
@@ -1351,11 +1351,8 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
}
if (hasFXAA) {
bool const preserveAlphaChannel =
// we're transparent -- alpha channel has user data
needsAlphaChannel ||
// the color-grading pass outputted the luminance channel, and we have an upscaling pass
(hasColorGrading && colorGradingConfig.outputLuminance && scaled);
bool const preserveAlphaChannel = needsAlphaChannel ||
(hasColorGrading && colorGradingConfig.outputLuminance);
input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat, preserveAlphaChannel);
// the padded buffer is resolved now
xvp.left = xvp.bottom = 0;
@@ -1443,6 +1440,13 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
fg.compile();
#if FILAMENT_ENABLE_FGVIEWER
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
if (UTILS_LIKELY(fgviewerServer)) {
fgviewerServer->update(view.getViewHandle(), fg.getFrameGraphInfo(view.getName()));
}
#endif
//fg.export_graphviz(slog.d, view.getName());
fg.execute(driver);
+1 -1
View File
@@ -174,7 +174,7 @@ void FSkinningBuffer::setBones(FEngine& engine, Handle<HwBufferObject> handle,
}
// This value is limited by ES3.0, ES3.0 only guarantees 2048.
// When you change this value, you must change MAX_SKINNING_BUFFER_WIDTH at getters.vs
// When you change this value, you must change MAX_SKINNING_BUFFER_WIDTH at surface_getters.vs
constexpr size_t MAX_SKINNING_BUFFER_WIDTH = 2048;
static inline size_t getSkinningBufferWidth(size_t const pairCount) noexcept {
+15
View File
@@ -109,6 +109,14 @@ FView::FView(FEngine& engine)
}
#endif
#if FILAMENT_ENABLE_FGVIEWER
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
if (UTILS_LIKELY(fgviewerServer)) {
mFrameGraphViewerViewHandle =
fgviewerServer->createView(utils::CString(getName()));
}
#endif
// allocate UBOs
mLightUbh = driver.createBufferObject(CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib),
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
@@ -153,6 +161,13 @@ void FView::terminate(FEngine& engine) {
engine.getDebugRegistry().unregisterDataSource("d.view.frame_info");
}
#endif
#if FILAMENT_ENABLE_FGVIEWER
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
if (UTILS_LIKELY(fgviewerServer)) {
fgviewerServer->destroyView(mFrameGraphViewerViewHandle);
}
#endif
}
void FView::setViewport(filament::Viewport const& viewport) noexcept {
+14
View File
@@ -60,6 +60,14 @@
#include <utils/Range.h>
#include <utils/Slice.h>
#if FILAMENT_ENABLE_FGVIEWER
#include <fgviewer/DebugServer.h>
#else
namespace filament::fgviewer {
using ViewHandle = uint32_t;
}
#endif
#include <math/scalar.h>
#include <math/mat4.h>
@@ -467,6 +475,10 @@ public:
return mUniforms;
}
fgviewer::ViewHandle getViewHandle() const noexcept {
return mFrameGraphViewerViewHandle;
}
private:
struct FPickingQuery : public PickingQuery {
private:
@@ -600,6 +612,8 @@ private:
{ 0, 0, 0, 1 },
}};
fgviewer::ViewHandle mFrameGraphViewerViewHandle;
#ifndef NDEBUG
struct DebugState {
std::unique_ptr<std::array<DebugRegistry::FrameHistory, 5*60>> debugFrameHistory{};
+55
View File
@@ -479,6 +479,61 @@ void FrameGraph::export_graphviz(utils::io::ostream& out, char const* name) {
mGraph.export_graphviz(out, name);
}
fgviewer::FrameGraphInfo FrameGraph::getFrameGraphInfo(const char *viewName) const {
#if FILAMENT_ENABLE_FGVIEWER
fgviewer::FrameGraphInfo info{utils::CString(viewName)};
std::vector<fgviewer::FrameGraphInfo::Pass> passes;
auto first = mPassNodes.begin();
const auto activePassNodesEnd = mActivePassNodesEnd;
while (first != activePassNodesEnd) {
PassNode *const pass = *first;
first++;
assert_invariant(!pass->isCulled());
std::vector<fgviewer::ResourceId> reads;
auto const &readEdges = mGraph.getIncomingEdges(pass);
for (auto const &edge: readEdges) {
// all incoming edges should be valid by construction
assert_invariant(mGraph.isEdgeValid(edge));
reads.push_back(edge->from);
}
std::vector<fgviewer::ResourceId> writes;
auto const &writeEdges = mGraph.getOutgoingEdges(pass);
for (auto const &edge: writeEdges) {
// It is possible that the node we're writing to has been culled.
// In this case we'd like to ignore the edge.
if (!mGraph.isEdgeValid(edge)) {
continue;
}
writes.push_back(edge->to);
}
passes.emplace_back(utils::CString(pass->getName()),
std::move(reads), std::move(writes));
}
std::unordered_map<fgviewer::ResourceId, fgviewer::FrameGraphInfo::Resource> resources;
for (const auto &resource: mResourceNodes) {
std::vector<fgviewer::FrameGraphInfo::Resource::Property> resourceProps;
// TODO: Fill in resource properties
fgviewer::ResourceId id = resource->getId();
resources.emplace(id, fgviewer::FrameGraphInfo::Resource(
id, utils::CString(resource->getName()),
std::move(resourceProps))
);
}
info.setResources(std::move(resources));
info.setPasses(std::move(passes));
return info;
#else
return fgviewer::FrameGraphInfo();
#endif
}
// ------------------------------------------------------------------------------------------------
/*
+14
View File
@@ -36,6 +36,14 @@
#include <functional>
#if FILAMENT_ENABLE_FGVIEWER
#include <fgviewer/FrameGraphInfo.h>
#else
namespace filament::fgviewer {
class FrameGraphInfo{};
} // namespace filament::fgviewer
#endif
namespace filament {
class ResourceAllocatorInterface;
@@ -434,6 +442,12 @@ public:
//! export a graphviz view of the graph
void export_graphviz(utils::io::ostream& out, const char* name = nullptr);
/**
* Export a fgviewer::FrameGraphInfo for current graph.
* Note that this function should be called after FrameGraph::compile().
*/
fgviewer::FrameGraphInfo getFrameGraphInfo(const char *viewName) const;
private:
friend class FrameGraphResources;
friend class PassNode;
+4
View File
@@ -26,9 +26,11 @@ namespace filament {
using namespace math;
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wignored-qualifiers"
#endif
#define A_CPU 1
#include "materials/fsr/ffx_a.h"
@@ -36,7 +38,9 @@ using namespace math;
#define FSR_RCAS_F 1
#include "materials/fsr/ffx_fsr1.h"
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
void FSR_ScalingSetup(FSRUniforms* outUniforms, FSRScalingConfig config) noexcept {
// FsrEasu API claims it needs the left-top offset, however that's not true with OpenGL,
@@ -83,8 +83,8 @@ vertex {
fragment {
#include "../../../../shaders/src/dithering.fs"
#include "../../../../shaders/src/vignette.fs"
#include "../../../../shaders/src/inline_dithering.fs"
#include "../../../../shaders/src/inline_vignette.fs"
#include "colorGrading.fs"
void dummy(){}
@@ -71,8 +71,8 @@ vertex {
fragment {
#include "../../../../shaders/src/dithering.fs"
#include "../../../../shaders/src/vignette.fs"
#include "../../../../shaders/src/inline_dithering.fs"
#include "../../../../shaders/src/inline_vignette.fs"
#include "colorGrading.fs"
void dummy(){}
+2 -1
View File
@@ -72,7 +72,8 @@ nil if there is none)."
(brace-list-intro . c-filament-style-lineup-brace-list-intro)
(brace-list-entry . c-filament-style-lineup-brace-list-entry)
(brace-list-close . c-filament-style-lineup-brace-list-entry)
(label . [0]))))
(label . [0])
(member-init-intro . ++))))
(provide 'c-filament-style)
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.56.8"
spec.version = "1.56.7"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.8/filament-v1.56.8-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.7/filament-v1.56.7-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
@@ -31,8 +31,6 @@ namespace filament::fgviewer {
using ViewHandle = uint32_t;
/**
* Server-side frame graph debugger.
*
@@ -727,7 +727,7 @@ public:
static constexpr size_t MAX_DEPTH_OUTPUT = 1;
static_assert(MAX_COLOR_OUTPUT == 8,
"When updating MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT, manually update post_process_inputs.fs"
" and post_process.fs");
" and post_process_main.fs");
// Preview the first shader generated by the given CodeGenParams.
// This is used to run Static Code Analysis before generating a package.
+6 -6
View File
@@ -937,15 +937,15 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
// explicitly remove them when using filamat lite.
std::string shader;
if (v.stage == backend::ShaderStage::VERTEX) {
shader = sg.createVertexProgram(
shader = sg.createSurfaceVertexProgram(
shaderModel, targetApi, targetLanguage, featureLevel,
info, v.variant, mInterpolation, mVertexDomain);
} else if (v.stage == backend::ShaderStage::FRAGMENT) {
shader = sg.createFragmentProgram(
shader = sg.createSurfaceFragmentProgram(
shaderModel, targetApi, targetLanguage, featureLevel,
info, v.variant, mInterpolation, mVariantFilter);
} else if (v.stage == backend::ShaderStage::COMPUTE) {
shader = sg.createComputeProgram(
shader = sg.createSurfaceComputeProgram(
shaderModel, targetApi, targetLanguage, featureLevel,
info);
}
@@ -1438,15 +1438,15 @@ std::string MaterialBuilder::peek(backend::ShaderStage stage,
switch (stage) {
case backend::ShaderStage::VERTEX:
return sg.createVertexProgram(
return sg.createSurfaceVertexProgram(
params.shaderModel, params.targetApi, params.targetLanguage,
params.featureLevel, info, {}, mInterpolation, mVertexDomain);
case backend::ShaderStage::FRAGMENT:
return sg.createFragmentProgram(
return sg.createSurfaceFragmentProgram(
params.shaderModel, params.targetApi, params.targetLanguage,
params.featureLevel, info, {}, mInterpolation, mVariantFilter);
case backend::ShaderStage::COMPUTE:
return sg.createComputeProgram(
return sg.createSurfaceComputeProgram(
params.shaderModel, params.targetApi, params.targetLanguage,
params.featureLevel, info);
}
+99 -90
View File
@@ -42,7 +42,7 @@ io::sstream& CodeGenerator::generateSeparator(io::sstream& out) {
return out;
}
utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, ShaderStage stage,
utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out, ShaderStage stage,
MaterialInfo const& material, filament::Variant v) const {
switch (mShaderModel) {
case ShaderModel::MOBILE:
@@ -78,7 +78,11 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
out << "#endif\n\n";
break;
case StereoscopicType::MULTIVIEW:
out << "#extension GL_OVR_multiview2 : require\n";
if (mTargetApi == TargetApi::VULKAN) {
out << "#extension GL_EXT_multiview : enable\n";
} else {
out << "#extension GL_OVR_multiview2 : require\n";
}
break;
case StereoscopicType::NONE:
break;
@@ -101,7 +105,11 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
// Nothing to generate
break;
case StereoscopicType::MULTIVIEW:
out << "#extension GL_OVR_multiview2 : require\n";
if (mTargetApi == TargetApi::VULKAN) {
out << "#extension GL_EXT_multiview : enable\n";
} else {
out << "#extension GL_OVR_multiview2 : require\n";
}
break;
case StereoscopicType::NONE:
break;
@@ -124,7 +132,9 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
// Nothing to generate
break;
case StereoscopicType::MULTIVIEW:
out << "layout(num_views = " << material.stereoscopicEyeCount << ") in;\n";
if (mTargetApi != TargetApi::VULKAN) {
out << "layout(num_views = " << material.stereoscopicEyeCount << ") in;\n";
}
break;
case StereoscopicType::NONE:
break;
@@ -324,7 +334,7 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
+ReservedSpecializationConstants::CONFIG_DEBUG_FROXEL_VISUALIZATION, false);
// Workaround a Metal pipeline compilation error with the message:
// "Could not statically determine the target of a texture". See light_indirect.fs
// "Could not statically determine the target of a texture". See surface_light_indirect.fs
generateSpecializationConstant(out, "CONFIG_STATIC_TEXTURE_TARGET_WORKAROUND",
+ReservedSpecializationConstants::CONFIG_STATIC_TEXTURE_TARGET_WORKAROUND, false);
@@ -355,6 +365,8 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
out << '\n';
out << SHADERS_COMMON_DEFINES_GLSL_DATA;
CodeGenerator::generateDefine(out, "MATERIAL_FEATURE_LEVEL", uint32_t(mFeatureLevel));
if (material.featureLevel == FeatureLevel::FEATURE_LEVEL_0 &&
(mFeatureLevel > FeatureLevel::FEATURE_LEVEL_0
|| mTargetLanguage == TargetLanguage::SPIRV)) {
@@ -409,21 +421,21 @@ Precision CodeGenerator::getDefaultUniformPrecision() const {
}
}
io::sstream& CodeGenerator::generateEpilog(io::sstream& out) {
io::sstream& CodeGenerator::generateCommonEpilog(io::sstream& out) {
out << "\n"; // For line compression all shaders finish with a newline character.
return out;
}
io::sstream& CodeGenerator::generateCommonTypes(io::sstream& out, ShaderStage stage) {
io::sstream& CodeGenerator::generateSurfaceTypes(io::sstream& out, ShaderStage stage) {
out << '\n';
switch (stage) {
case ShaderStage::VERTEX:
out << '\n';
out << SHADERS_COMMON_TYPES_GLSL_DATA;
out << SHADERS_SURFACE_TYPES_GLSL_DATA;
break;
case ShaderStage::FRAGMENT:
out << '\n';
out << SHADERS_COMMON_TYPES_GLSL_DATA;
out << SHADERS_SURFACE_TYPES_GLSL_DATA;
break;
case ShaderStage::COMPUTE:
break;
@@ -431,31 +443,31 @@ io::sstream& CodeGenerator::generateCommonTypes(io::sstream& out, ShaderStage st
return out;
}
io::sstream& CodeGenerator::generateShaderMain(io::sstream& out, ShaderStage stage) {
io::sstream& CodeGenerator::generateSurfaceMain(io::sstream& out, ShaderStage stage) {
switch (stage) {
case ShaderStage::VERTEX:
out << SHADERS_MAIN_VS_DATA;
out << SHADERS_SURFACE_MAIN_VS_DATA;
break;
case ShaderStage::FRAGMENT:
out << SHADERS_MAIN_FS_DATA;
out << SHADERS_SURFACE_MAIN_FS_DATA;
break;
case ShaderStage::COMPUTE:
out << SHADERS_MAIN_CS_DATA;
out << SHADERS_SURFACE_MAIN_CS_DATA;
break;
}
return out;
}
io::sstream& CodeGenerator::generatePostProcessMain(io::sstream& out, ShaderStage type) {
if (type == ShaderStage::VERTEX) {
out << SHADERS_POST_PROCESS_VS_DATA;
} else if (type == ShaderStage::FRAGMENT) {
out << SHADERS_POST_PROCESS_FS_DATA;
io::sstream& CodeGenerator::generatePostProcessMain(io::sstream& out, ShaderStage stage) {
if (stage == ShaderStage::VERTEX) {
out << SHADERS_POST_PROCESS_MAIN_VS_DATA;
} else if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_POST_PROCESS_MAIN_FS_DATA;
}
return out;
}
io::sstream& CodeGenerator::generateVariable(io::sstream& out, ShaderStage stage,
io::sstream& CodeGenerator::generateCommonVariable(io::sstream& out, ShaderStage stage,
const MaterialBuilder::CustomVariable& variable, size_t index) {
auto const& name = variable.name;
const char* precisionString = getPrecisionQualifier(variable.precision);
@@ -475,7 +487,7 @@ io::sstream& CodeGenerator::generateVariable(io::sstream& out, ShaderStage stage
return out;
}
io::sstream& CodeGenerator::generateShaderInputs(io::sstream& out, ShaderStage type,
io::sstream& CodeGenerator::generateSurfaceInputs(io::sstream& out, ShaderStage stage,
const AttributeBitset& attributes, Interpolation interpolation,
MaterialBuilder::PushConstantList const& pushConstants) const {
auto const& attributeDatabase = MaterialBuilder::getAttributeDatabase();
@@ -488,7 +500,7 @@ io::sstream& CodeGenerator::generateShaderInputs(io::sstream& out, ShaderStage t
generateDefine(out, attributeDatabase[i].getDefineName().c_str(), true);
});
if (type == ShaderStage::VERTEX) {
if (stage == ShaderStage::VERTEX) {
out << "\n";
attributes.forEachSetBit([&out, &attributeDatabase, this](size_t i) {
auto const& attribute = attributeDatabase[i];
@@ -507,16 +519,17 @@ io::sstream& CodeGenerator::generateShaderInputs(io::sstream& out, ShaderStage t
}
out << "\n";
out << SHADERS_VARYINGS_GLSL_DATA;
out << SHADERS_COMMON_VARYINGS_GLSL_DATA;
out << SHADERS_SURFACE_VARYINGS_GLSL_DATA;
return out;
}
io::sstream& CodeGenerator::generateOutput(io::sstream& out, ShaderStage type,
io::sstream& CodeGenerator::generateOutput(io::sstream& out, ShaderStage stage,
const CString& name, size_t index,
MaterialBuilder::VariableQualifier qualifier,
MaterialBuilder::Precision precision,
MaterialBuilder::OutputType outputType) const {
if (name.empty() || type == ShaderStage::VERTEX) {
if (name.empty() || stage == ShaderStage::VERTEX) {
return out;
}
@@ -577,10 +590,10 @@ io::sstream& CodeGenerator::generateOutput(io::sstream& out, ShaderStage type,
}
io::sstream& CodeGenerator::generateDepthShaderMain(io::sstream& out, ShaderStage type) {
assert(type != ShaderStage::VERTEX);
if (type == ShaderStage::FRAGMENT) {
out << SHADERS_DEPTH_MAIN_FS_DATA;
io::sstream& CodeGenerator::generateSurfaceDepthMain(io::sstream& out, ShaderStage stage) {
assert(stage != ShaderStage::VERTEX);
if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_SURFACE_DEPTH_MAIN_FS_DATA;
}
return out;
}
@@ -776,7 +789,7 @@ io::sstream& CodeGenerator::generateBufferInterfaceBlock(io::sstream& out, Shade
return out;
}
io::sstream& CodeGenerator::generateSamplers(utils::io::sstream& out,
io::sstream& CodeGenerator::generateCommonSamplers(utils::io::sstream& out,
filament::DescriptorSetBindingPoints set,
filament::SamplerInterfaceBlock::SamplerInfoList const& list) const {
if (list.empty()) {
@@ -825,7 +838,7 @@ io::sstream& CodeGenerator::generateSamplers(utils::io::sstream& out,
return out;
}
io::sstream& CodeGenerator::generateSubpass(io::sstream& out, SubpassInfo subpass) {
io::sstream& CodeGenerator::generatePostProcessSubpass(io::sstream& out, SubpassInfo subpass) {
if (!subpass.isValid) {
return out;
}
@@ -1013,21 +1026,19 @@ io::sstream& CodeGenerator::generateQualityDefine(io::sstream& out, ShaderQualit
return out;
}
io::sstream& CodeGenerator::generateCommon(io::sstream& out, ShaderStage stage) {
io::sstream& CodeGenerator::generateSurfaceCommon(io::sstream& out, ShaderStage stage) {
out << SHADERS_COMMON_MATH_GLSL_DATA;
switch (stage) {
case ShaderStage::VERTEX:
out << SHADERS_COMMON_INSTANCING_GLSL_DATA;
out << SHADERS_COMMON_SHADOWING_GLSL_DATA;
out << SHADERS_SURFACE_INSTANCING_GLSL_DATA;
out << SHADERS_SURFACE_SHADOWING_GLSL_DATA;
break;
case ShaderStage::FRAGMENT:
out << SHADERS_COMMON_INSTANCING_GLSL_DATA;
out << SHADERS_COMMON_SHADOWING_GLSL_DATA;
out << SHADERS_SURFACE_INSTANCING_GLSL_DATA;
out << SHADERS_SURFACE_SHADOWING_GLSL_DATA;
out << SHADERS_COMMON_SHADING_FS_DATA;
out << SHADERS_COMMON_GRAPHICS_FS_DATA;
out << SHADERS_COMMON_MATERIAL_FS_DATA;
out << SHADERS_SURFACE_MATERIAL_FS_DATA;
break;
case ShaderStage::COMPUTE:
out << '\n';
@@ -1037,89 +1048,88 @@ io::sstream& CodeGenerator::generateCommon(io::sstream& out, ShaderStage stage)
return out;
}
io::sstream& CodeGenerator::generatePostProcessCommon(io::sstream& out, ShaderStage type) {
io::sstream& CodeGenerator::generatePostProcessCommon(io::sstream& out, ShaderStage stage) {
out << SHADERS_COMMON_MATH_GLSL_DATA;
if (type == ShaderStage::VERTEX) {
} else if (type == ShaderStage::FRAGMENT) {
if (stage == ShaderStage::VERTEX) {
} else if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_COMMON_SHADING_FS_DATA;
out << SHADERS_COMMON_GRAPHICS_FS_DATA;
}
return out;
}
io::sstream& CodeGenerator::generateFog(io::sstream& out, ShaderStage type) {
if (type == ShaderStage::VERTEX) {
} else if (type == ShaderStage::FRAGMENT) {
out << SHADERS_FOG_FS_DATA;
io::sstream& CodeGenerator::generateSurfaceFog(io::sstream& out, ShaderStage stage) {
if (stage == ShaderStage::VERTEX) {
} else if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_SURFACE_FOG_FS_DATA;
}
return out;
}
io::sstream& CodeGenerator::generateCommonMaterial(io::sstream& out, ShaderStage type) {
if (type == ShaderStage::VERTEX) {
out << SHADERS_MATERIAL_INPUTS_VS_DATA;
} else if (type == ShaderStage::FRAGMENT) {
out << SHADERS_MATERIAL_INPUTS_FS_DATA;
io::sstream& CodeGenerator::generateSurfaceMaterial(io::sstream& out, ShaderStage stage) {
if (stage == ShaderStage::VERTEX) {
out << SHADERS_SURFACE_MATERIAL_INPUTS_VS_DATA;
} else if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_SURFACE_MATERIAL_INPUTS_FS_DATA;
}
return out;
}
io::sstream& CodeGenerator::generatePostProcessInputs(io::sstream& out, ShaderStage type) {
if (type == ShaderStage::VERTEX) {
io::sstream& CodeGenerator::generatePostProcessInputs(io::sstream& out, ShaderStage stage) {
out << SHADERS_COMMON_VARYINGS_GLSL_DATA;
if (stage == ShaderStage::VERTEX) {
out << SHADERS_POST_PROCESS_INPUTS_VS_DATA;
} else if (type == ShaderStage::FRAGMENT) {
} else if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_POST_PROCESS_INPUTS_FS_DATA;
}
return out;
}
io::sstream& CodeGenerator::generatePostProcessGetters(io::sstream& out, ShaderStage type) {
io::sstream& CodeGenerator::generatePostProcessGetters(io::sstream& out, ShaderStage stage) {
out << SHADERS_COMMON_GETTERS_GLSL_DATA;
if (type == ShaderStage::VERTEX) {
if (stage == ShaderStage::VERTEX) {
out << SHADERS_POST_PROCESS_GETTERS_VS_DATA;
} else if (type == ShaderStage::FRAGMENT) {
} else if (stage == ShaderStage::FRAGMENT) {
}
return out;
}
io::sstream& CodeGenerator::generateGetters(io::sstream& out, ShaderStage stage) {
io::sstream& CodeGenerator::generateSurfaceGetters(io::sstream& out, ShaderStage stage) {
out << SHADERS_COMMON_GETTERS_GLSL_DATA;
switch (stage) {
case ShaderStage::VERTEX:
out << SHADERS_GETTERS_VS_DATA;
out << SHADERS_SURFACE_GETTERS_VS_DATA;
break;
case ShaderStage::FRAGMENT:
out << SHADERS_GETTERS_FS_DATA;
out << SHADERS_SURFACE_GETTERS_FS_DATA;
break;
case ShaderStage::COMPUTE:
out << SHADERS_GETTERS_CS_DATA;
out << SHADERS_SURFACE_GETTERS_CS_DATA;
break;
}
return out;
}
io::sstream& CodeGenerator::generateParameters(io::sstream& out, ShaderStage type) {
if (type == ShaderStage::VERTEX) {
} else if (type == ShaderStage::FRAGMENT) {
out << SHADERS_SHADING_PARAMETERS_FS_DATA;
io::sstream& CodeGenerator::generateSurfaceParameters(io::sstream& out, ShaderStage stage) {
if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_SURFACE_SHADING_PARAMETERS_FS_DATA;
}
return out;
}
io::sstream& CodeGenerator::generateShaderLit(io::sstream& out, ShaderStage type,
io::sstream& CodeGenerator::generateSurfaceLit(io::sstream& out, ShaderStage stage,
filament::Variant variant, Shading shading, bool customSurfaceShading) {
if (type == ShaderStage::VERTEX) {
} else if (type == ShaderStage::FRAGMENT) {
out << SHADERS_COMMON_LIGHTING_FS_DATA;
if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_SURFACE_LIGHTING_FS_DATA;
if (filament::Variant::isShadowReceiverVariant(variant)) {
out << SHADERS_SHADOWING_FS_DATA;
out << SHADERS_SURFACE_SHADOWING_FS_DATA;
}
// the only reason we have this assert here is that we used to have a check,
// which seemed unnecessary.
assert_invariant(shading != Shading::UNLIT);
out << SHADERS_BRDF_FS_DATA;
out << SHADERS_SURFACE_BRDF_FS_DATA;
switch (shading) {
case Shading::UNLIT:
// can't happen
@@ -1127,54 +1137,53 @@ io::sstream& CodeGenerator::generateShaderLit(io::sstream& out, ShaderStage type
case Shading::SPECULAR_GLOSSINESS:
case Shading::LIT:
if (customSurfaceShading) {
out << SHADERS_SHADING_LIT_CUSTOM_FS_DATA;
out << SHADERS_SURFACE_SHADING_LIT_CUSTOM_FS_DATA;
} else {
out << SHADERS_SHADING_MODEL_STANDARD_FS_DATA;
out << SHADERS_SURFACE_SHADING_MODEL_STANDARD_FS_DATA;
}
break;
case Shading::SUBSURFACE:
out << SHADERS_SHADING_MODEL_SUBSURFACE_FS_DATA;
out << SHADERS_SURFACE_SHADING_MODEL_SUBSURFACE_FS_DATA;
break;
case Shading::CLOTH:
out << SHADERS_SHADING_MODEL_CLOTH_FS_DATA;
out << SHADERS_SURFACE_SHADING_MODEL_CLOTH_FS_DATA;
break;
}
out << SHADERS_AMBIENT_OCCLUSION_FS_DATA;
out << SHADERS_LIGHT_INDIRECT_FS_DATA;
out << SHADERS_SURFACE_AMBIENT_OCCLUSION_FS_DATA;
out << SHADERS_SURFACE_LIGHT_INDIRECT_FS_DATA;
if (variant.hasDirectionalLighting()) {
out << SHADERS_LIGHT_DIRECTIONAL_FS_DATA;
out << SHADERS_SURFACE_LIGHT_DIRECTIONAL_FS_DATA;
}
if (variant.hasDynamicLighting()) {
out << SHADERS_LIGHT_PUNCTUAL_FS_DATA;
out << SHADERS_SURFACE_LIGHT_PUNCTUAL_FS_DATA;
}
out << SHADERS_SHADING_LIT_FS_DATA;
out << SHADERS_SURFACE_SHADING_LIT_FS_DATA;
}
return out;
}
io::sstream& CodeGenerator::generateShaderUnlit(io::sstream& out, ShaderStage type,
io::sstream& CodeGenerator::generateSurfaceUnlit(io::sstream& out, ShaderStage stage,
filament::Variant variant, bool hasShadowMultiplier) {
if (type == ShaderStage::VERTEX) {
} else if (type == ShaderStage::FRAGMENT) {
if (stage == ShaderStage::FRAGMENT) {
if (hasShadowMultiplier) {
if (filament::Variant::isShadowReceiverVariant(variant)) {
out << SHADERS_SHADOWING_FS_DATA;
out << SHADERS_SURFACE_SHADOWING_FS_DATA;
}
}
out << SHADERS_SHADING_UNLIT_FS_DATA;
out << SHADERS_SURFACE_SHADING_UNLIT_FS_DATA;
}
return out;
}
io::sstream& CodeGenerator::generateShaderReflections(utils::io::sstream& out, ShaderStage type) {
if (type == ShaderStage::VERTEX) {
} else if (type == ShaderStage::FRAGMENT) {
out << SHADERS_COMMON_LIGHTING_FS_DATA;
out << SHADERS_LIGHT_REFLECTIONS_FS_DATA;
out << SHADERS_SHADING_REFLECTIONS_FS_DATA;
io::sstream& CodeGenerator::generateSurfaceReflections(utils::io::sstream& out,
ShaderStage stage) {
if (stage == ShaderStage::FRAGMENT) {
out << SHADERS_SURFACE_LIGHTING_FS_DATA;
out << SHADERS_SURFACE_LIGHT_REFLECTIONS_FS_DATA;
out << SHADERS_SURFACE_SHADING_REFLECTIONS_FS_DATA;
}
return out;
}
+24 -24
View File
@@ -75,68 +75,68 @@ public:
static utils::io::sstream& generateSeparator(utils::io::sstream& out);
// generate prolog for the given shader
utils::io::sstream& generateProlog(utils::io::sstream& out, ShaderStage stage,
utils::io::sstream& generateCommonProlog(utils::io::sstream& out, ShaderStage stage,
MaterialInfo const& material, filament::Variant v) const;
static utils::io::sstream& generateEpilog(utils::io::sstream& out);
static utils::io::sstream& generateCommonEpilog(utils::io::sstream& out);
static utils::io::sstream& generateCommonTypes(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generateSurfaceTypes(utils::io::sstream& out, ShaderStage stage);
// generate common functions for the given shader
static utils::io::sstream& generateCommon(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generatePostProcessCommon(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generateCommonMaterial(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generateSurfaceCommon(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generatePostProcessCommon(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generateSurfaceMaterial(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generateFog(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generateSurfaceFog(utils::io::sstream& out, ShaderStage stage);
// generate the shader's main()
static utils::io::sstream& generateShaderMain(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generatePostProcessMain(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generateSurfaceMain(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generatePostProcessMain(utils::io::sstream& out, ShaderStage stage);
// generate the shader's code for the lit shading model
static utils::io::sstream& generateShaderLit(utils::io::sstream& out, ShaderStage type,
static utils::io::sstream& generateSurfaceLit(utils::io::sstream& out, ShaderStage stage,
filament::Variant variant, filament::Shading shading, bool customSurfaceShading);
// generate the shader's code for the unlit shading model
static utils::io::sstream& generateShaderUnlit(utils::io::sstream& out, ShaderStage type,
static utils::io::sstream& generateSurfaceUnlit(utils::io::sstream& out, ShaderStage stage,
filament::Variant variant, bool hasShadowMultiplier);
// generate the shader's code for the screen-space reflections
static utils::io::sstream& generateShaderReflections(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generateSurfaceReflections(utils::io::sstream& out, ShaderStage stage);
// generate declarations for custom interpolants
static utils::io::sstream& generateVariable(utils::io::sstream& out, ShaderStage stage,
static utils::io::sstream& generateCommonVariable(utils::io::sstream& out, ShaderStage stage,
const MaterialBuilder::CustomVariable& variable, size_t index);
// generate declarations for non-custom "in" variables
utils::io::sstream& generateShaderInputs(utils::io::sstream& out, ShaderStage type,
utils::io::sstream& generateSurfaceInputs(utils::io::sstream& out, ShaderStage stage,
const filament::AttributeBitset& attributes, filament::Interpolation interpolation,
MaterialBuilder::PushConstantList const& pushConstants) const;
static utils::io::sstream& generatePostProcessInputs(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generatePostProcessInputs(utils::io::sstream& out, ShaderStage stage);
// generate declarations for custom output variables
utils::io::sstream& generateOutput(utils::io::sstream& out, ShaderStage type,
utils::io::sstream& generateOutput(utils::io::sstream& out, ShaderStage stage,
const utils::CString& name, size_t index,
MaterialBuilder::VariableQualifier qualifier,
MaterialBuilder::Precision precision,
MaterialBuilder::OutputType outputType) const;
// generate no-op shader for depth prepass
static utils::io::sstream& generateDepthShaderMain(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generateSurfaceDepthMain(utils::io::sstream& out, ShaderStage stage);
// generate samplers
utils::io::sstream& generateSamplers(utils::io::sstream& out,
utils::io::sstream& generateCommonSamplers(utils::io::sstream& out,
filament::DescriptorSetBindingPoints set,
filament::SamplerInterfaceBlock::SamplerInfoList const& list) const;
utils::io::sstream& generateSamplers(utils::io::sstream& out,
utils::io::sstream& generateCommonSamplers(utils::io::sstream& out,
filament::DescriptorSetBindingPoints set,
const filament::SamplerInterfaceBlock& sib) const {
return generateSamplers(out, set, sib.getSamplerInfoList());
return generateCommonSamplers(out, set, sib.getSamplerInfoList());
}
// generate subpass
static utils::io::sstream& generateSubpass(utils::io::sstream& out,
static utils::io::sstream& generatePostProcessSubpass(utils::io::sstream& out,
filament::SubpassInfo subpass);
// generate uniforms
@@ -174,9 +174,9 @@ public:
MaterialBuilder::PushConstantList const& pushConstants,
size_t const layoutLocation) const;
static utils::io::sstream& generatePostProcessGetters(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generateGetters(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generateParameters(utils::io::sstream& out, ShaderStage type);
static utils::io::sstream& generatePostProcessGetters(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generateSurfaceGetters(utils::io::sstream& out, ShaderStage stage);
static utils::io::sstream& generateSurfaceParameters(utils::io::sstream& out, ShaderStage stage);
static void fixupExternalSamplers(
std::string& shader, filament::SamplerInterfaceBlock const& sib,
+47 -49
View File
@@ -81,7 +81,6 @@ void ShaderGenerator::generateSurfaceMaterialVariantDefines(utils::io::sstream&
}
out << '\n';
CodeGenerator::generateDefine(out, "MATERIAL_FEATURE_LEVEL", uint32_t(featureLevel));
CodeGenerator::generateDefine(out, "MATERIAL_HAS_SHADOW_MULTIPLIER",
material.hasShadowMultiplier);
@@ -370,7 +369,7 @@ void ShaderGenerator::fixupExternalSamplers(ShaderModel sm, std::string& shader,
}
}
std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, const filament::Variant variant, Interpolation interpolation,
@@ -389,7 +388,7 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
const CodeGenerator cg(shaderModel, targetApi, targetLanguage, featureLevel);
cg.generateProlog(vs, ShaderStage::VERTEX, material, variant);
cg.generateCommonProlog(vs, ShaderStage::VERTEX, material, variant);
generateUserSpecConstants(cg, vs, mConstants);
@@ -436,15 +435,15 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
[](MaterialBuilder::PushConstant const& constant) {
return constant.stage == ShaderStage::VERTEX;
});
cg.generateShaderInputs(vs, ShaderStage::VERTEX, attributes, interpolation,
cg.generateSurfaceInputs(vs, ShaderStage::VERTEX, attributes, interpolation,
vertexPushConstants);
CodeGenerator::generateCommonTypes(vs, ShaderStage::VERTEX);
CodeGenerator::generateSurfaceTypes(vs, ShaderStage::VERTEX);
// custom material variables
size_t variableIndex = 0;
for (const auto& variable : mVariables) {
CodeGenerator::generateVariable(vs, ShaderStage::VERTEX, variable, variableIndex++);
CodeGenerator::generateCommonVariable(vs, ShaderStage::VERTEX, variable, variableIndex++);
}
// materials defines
@@ -478,7 +477,7 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
DescriptorSetBindingPoints::PER_RENDERABLE,
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
UibGenerator::getPerRenderableMorphingUib());
cg.generateSamplers(vs, DescriptorSetBindingPoints::PER_RENDERABLE,
cg.generateCommonSamplers(vs, DescriptorSetBindingPoints::PER_RENDERABLE,
SibGenerator::getPerRenderableSib(variant));
}
@@ -489,23 +488,23 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
CodeGenerator::generateSeparator(vs);
cg.generateSamplers(vs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
cg.generateCommonSamplers(vs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
// shader code
CodeGenerator::generateCommon(vs, ShaderStage::VERTEX);
CodeGenerator::generateGetters(vs, ShaderStage::VERTEX);
CodeGenerator::generateCommonMaterial(vs, ShaderStage::VERTEX);
CodeGenerator::generateSurfaceCommon(vs, ShaderStage::VERTEX);
CodeGenerator::generateSurfaceGetters(vs, ShaderStage::VERTEX);
CodeGenerator::generateSurfaceMaterial(vs, ShaderStage::VERTEX);
// main entry point
appendShader(vs, mMaterialVertexCode, mMaterialVertexLineOffset);
CodeGenerator::generateShaderMain(vs, ShaderStage::VERTEX);
CodeGenerator::generateSurfaceMain(vs, ShaderStage::VERTEX);
CodeGenerator::generateEpilog(vs);
CodeGenerator::generateCommonEpilog(vs);
return vs.c_str();
}
std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, const filament::Variant variant,
@@ -522,7 +521,7 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
const CodeGenerator cg(shaderModel, targetApi, targetLanguage, featureLevel);
io::sstream fs;
cg.generateProlog(fs, ShaderStage::FRAGMENT, material, variant);
cg.generateCommonProlog(fs, ShaderStage::FRAGMENT, material, variant);
generateUserSpecConstants(cg, fs, mConstants);
@@ -546,15 +545,15 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
[](MaterialBuilder::PushConstant const& constant) {
return constant.stage == ShaderStage::FRAGMENT;
});
cg.generateShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes, interpolation,
cg.generateSurfaceInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes, interpolation,
fragmentPushConstants);
CodeGenerator::generateCommonTypes(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceTypes(fs, ShaderStage::FRAGMENT);
// custom material variables
size_t variableIndex = 0;
for (const auto& variable : mVariables) {
CodeGenerator::generateVariable(fs, ShaderStage::FRAGMENT, variable, variableIndex++);
CodeGenerator::generateCommonVariable(fs, ShaderStage::FRAGMENT, variable, variableIndex++);
}
// uniforms and samplers
@@ -626,21 +625,21 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
return pos == perViewDescriptorSetLayout.bindings.end();
}), list.end());
cg.generateSamplers(fs, DescriptorSetBindingPoints::PER_VIEW, list);
cg.generateCommonSamplers(fs, DescriptorSetBindingPoints::PER_VIEW, list);
}
cg.generateSamplers(fs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
cg.generateCommonSamplers(fs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
fs << "float filament_lodBias;\n";
// shading code
CodeGenerator::generateCommon(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateGetters(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateCommonMaterial(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateParameters(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceCommon(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceGetters(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceMaterial(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceParameters(fs, ShaderStage::FRAGMENT);
if (filament::Variant::isFogVariant(variant)) {
CodeGenerator::generateFog(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceFog(fs, ShaderStage::FRAGMENT);
}
// shading model
@@ -656,30 +655,30 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
}
// These variants are special and are treated as DEPTH variants. Filament will never
// request that variant for the color pass.
CodeGenerator::generateDepthShaderMain(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceDepthMain(fs, ShaderStage::FRAGMENT);
} else {
appendShader(fs, mMaterialFragmentCode, mMaterialLineOffset);
if (material.isLit) {
if (filament::Variant::isSSRVariant(variant)) {
CodeGenerator::generateShaderReflections(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceReflections(fs, ShaderStage::FRAGMENT);
} else {
CodeGenerator::generateShaderLit(fs, ShaderStage::FRAGMENT, variant,
CodeGenerator::generateSurfaceLit(fs, ShaderStage::FRAGMENT, variant,
material.shading,material.hasCustomSurfaceShading);
}
} else {
CodeGenerator::generateShaderUnlit(fs, ShaderStage::FRAGMENT, variant,
CodeGenerator::generateSurfaceUnlit(fs, ShaderStage::FRAGMENT, variant,
material.hasShadowMultiplier);
}
// entry point
CodeGenerator::generateShaderMain(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateSurfaceMain(fs, ShaderStage::FRAGMENT);
}
CodeGenerator::generateEpilog(fs);
CodeGenerator::generateCommonEpilog(fs);
return fs.c_str();
}
std::string ShaderGenerator::createComputeProgram(filament::backend::ShaderModel shaderModel,
std::string ShaderGenerator::createSurfaceComputeProgram(filament::backend::ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material) const noexcept {
@@ -688,11 +687,11 @@ std::string ShaderGenerator::createComputeProgram(filament::backend::ShaderModel
const CodeGenerator cg(shaderModel, targetApi, targetLanguage, featureLevel);
io::sstream s;
cg.generateProlog(s, ShaderStage::COMPUTE, material, {});
cg.generateCommonProlog(s, ShaderStage::COMPUTE, material, {});
generateUserSpecConstants(cg, s, mConstants);
CodeGenerator::generateCommonTypes(s, ShaderStage::COMPUTE);
CodeGenerator::generateSurfaceTypes(s, ShaderStage::COMPUTE);
cg.generateUniforms(s, ShaderStage::COMPUTE,
DescriptorSetBindingPoints::PER_VIEW,
@@ -704,22 +703,21 @@ std::string ShaderGenerator::createComputeProgram(filament::backend::ShaderModel
+PerMaterialBindingPoints::MATERIAL_PARAMS,
material.uib);
cg.generateSamplers(s, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
cg.generateCommonSamplers(s, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
// generate SSBO
cg.generateBuffers(s, material.buffers);
// TODO: generate images
CodeGenerator::generateCommon(s, ShaderStage::COMPUTE);
CodeGenerator::generateGetters(s, ShaderStage::COMPUTE);
CodeGenerator::generateSurfaceCommon(s, ShaderStage::COMPUTE);
CodeGenerator::generateSurfaceGetters(s, ShaderStage::COMPUTE);
appendShader(s, mMaterialFragmentCode, mMaterialLineOffset);
CodeGenerator::generateShaderMain(s, ShaderStage::COMPUTE);
CodeGenerator::generateSurfaceMain(s, ShaderStage::COMPUTE);
CodeGenerator::generateEpilog(s);
CodeGenerator::generateCommonEpilog(s);
return s.c_str();
}
@@ -729,7 +727,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
MaterialInfo const& material, const filament::Variant::type_t variantKey) const noexcept {
const CodeGenerator cg(sm, targetApi, targetLanguage, featureLevel);
io::sstream vs;
cg.generateProlog(vs, ShaderStage::VERTEX, material, {});
cg.generateCommonProlog(vs, ShaderStage::VERTEX, material, {});
generateUserSpecConstants(cg, vs, mConstants);
@@ -738,7 +736,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
// custom material variables
size_t variableIndex = 0;
for (const auto& variable : mVariables) {
CodeGenerator::generateVariable(vs, ShaderStage::VERTEX, variable, variableIndex++);
CodeGenerator::generateCommonVariable(vs, ShaderStage::VERTEX, variable, variableIndex++);
}
CodeGenerator::generatePostProcessInputs(vs, ShaderStage::VERTEX);
@@ -754,7 +752,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
+PerMaterialBindingPoints::MATERIAL_PARAMS,
material.uib);
cg.generateSamplers(vs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
cg.generateCommonSamplers(vs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
CodeGenerator::generatePostProcessCommon(vs, ShaderStage::VERTEX);
CodeGenerator::generatePostProcessGetters(vs, ShaderStage::VERTEX);
@@ -763,7 +761,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
CodeGenerator::generatePostProcessMain(vs, ShaderStage::VERTEX);
CodeGenerator::generateEpilog(vs);
CodeGenerator::generateCommonEpilog(vs);
return vs.c_str();
}
@@ -773,7 +771,7 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
MaterialInfo const& material, uint8_t variant) const noexcept {
const CodeGenerator cg(sm, targetApi, targetLanguage, featureLevel);
io::sstream fs;
cg.generateProlog(fs, ShaderStage::FRAGMENT, material, {});
cg.generateCommonProlog(fs, ShaderStage::FRAGMENT, material, {});
generateUserSpecConstants(cg, fs, mConstants);
@@ -782,7 +780,7 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
// custom material variables
size_t variableIndex = 0;
for (const auto& variable : mVariables) {
CodeGenerator::generateVariable(fs, ShaderStage::FRAGMENT, variable, variableIndex++);
CodeGenerator::generateCommonVariable(fs, ShaderStage::FRAGMENT, variable, variableIndex++);
}
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
@@ -795,10 +793,10 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
+PerMaterialBindingPoints::MATERIAL_PARAMS,
material.uib);
cg.generateSamplers(fs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
cg.generateCommonSamplers(fs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
// subpass
CodeGenerator::generateSubpass(fs, material.subpass);
CodeGenerator::generatePostProcessSubpass(fs, material.subpass);
CodeGenerator::generatePostProcessCommon(fs, ShaderStage::FRAGMENT);
CodeGenerator::generatePostProcessGetters(fs, ShaderStage::FRAGMENT);
@@ -819,7 +817,7 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
appendShader(fs, mMaterialFragmentCode, mMaterialLineOffset);
CodeGenerator::generatePostProcessMain(fs, ShaderStage::FRAGMENT);
CodeGenerator::generateEpilog(fs);
CodeGenerator::generateCommonEpilog(fs);
return fs.c_str();
}
+3 -3
View File
@@ -58,21 +58,21 @@ public:
size_t vertexLineOffset,
MaterialBuilder::MaterialDomain materialDomain) noexcept;
std::string createVertexProgram(filament::backend::ShaderModel shaderModel,
std::string createSurfaceVertexProgram(filament::backend::ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, filament::Variant variant,
filament::Interpolation interpolation,
filament::VertexDomain vertexDomain) const noexcept;
std::string createFragmentProgram(filament::backend::ShaderModel shaderModel,
std::string createSurfaceFragmentProgram(filament::backend::ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, filament::Variant variant,
filament::Interpolation interpolation,
filament::UserVariantFilterMask variantFilter) const noexcept;
std::string createComputeProgram(filament::backend::ShaderModel shaderModel,
std::string createSurfaceComputeProgram(filament::backend::ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material) const noexcept;
@@ -56,6 +56,8 @@ public:
explicit MeshAssimp(filament::Engine& engine);
~MeshAssimp();
// This function takes over the ownership of `materials` to prevent crashes due to the
// incorrect order of resource destruction.
void addFromFile(const utils::Path& path,
std::map<std::string, filament::MaterialInstance*>& materials,
bool overrideMaterial = false);
@@ -127,8 +129,9 @@ private:
filament::Material* mDefaultColorMaterial = nullptr;
filament::Material* mDefaultTransparentColorMaterial = nullptr;
mutable std::unordered_map<uint64_t, filament::Material*> mGltfMaterialCache;
std::map<std::string, filament::MaterialInstance*> mMaterialInstances;
filament::Texture* mDefaultMap = nullptr;
filament::Texture* mDefaultNormalMap = nullptr;
float mDefaultMetallic = 0.0f;
@@ -138,8 +141,6 @@ private:
std::vector<utils::Entity> mRenderables;
std::vector<filament::Texture*> mTextures;
};
#endif // TNT_FILAMENT_SAMPLE_MESH_ASSIMP_H
+12 -9
View File
@@ -277,26 +277,25 @@ MeshAssimp::MeshAssimp(Engine& engine) : mEngine(engine) {
}
MeshAssimp::~MeshAssimp() {
for (Entity renderable : mRenderables) {
mEngine.destroy(renderable);
}
mEngine.destroy(mVertexBuffer);
mEngine.destroy(mIndexBuffer);
for (auto& item : mMaterialInstances) {
mEngine.destroy(item.second);
}
mEngine.destroy(mDefaultColorMaterial);
mEngine.destroy(mDefaultTransparentColorMaterial);
mEngine.destroy(mDefaultNormalMap);
mEngine.destroy(mDefaultMap);
for (auto& item : mGltfMaterialCache) {
auto material = item.second;
mEngine.destroy(material);
}
for (Entity renderable : mRenderables) {
mEngine.destroy(renderable);
}
mEngine.destroy(mDefaultNormalMap);
mEngine.destroy(mDefaultMap);
for (Texture* texture : mTextures) {
mEngine.destroy(texture);
}
// destroy the Entities itself
EntityManager::get().destroy(mRenderables.size(), mRenderables.data());
}
@@ -626,6 +625,10 @@ void MeshAssimp::addFromFile(const Path& path,
tcm.getInstance(rootEntity) : tcm.getInstance(mRenderables[pindex]));
tcm.create(entity, parent, mesh.transform);
}
// Takes over the ownership of the material instances so that resources are gracefully
// destroyed in a correct order. The caller doesn't need to handle the destruction.
mMaterialInstances.swap(materials);
}
using Assimp::Importer;
+2 -1
View File
@@ -52,7 +52,7 @@ public:
static std::string_view const kSuccessHeader;
static std::string_view const kErrorHeader;
DebugServer(backend::Backend backend, int port);
DebugServer(backend::Backend backend, backend::ShaderLanguage shaderLanguage, int port);
~DebugServer();
/**
@@ -97,6 +97,7 @@ private:
const char* newShaderContent, size_t newShaderLength);
const backend::Backend mBackend;
const backend::ShaderLanguage mShaderLanguage;
CivetServer* mServer;
+2 -2
View File
@@ -46,8 +46,8 @@ public:
// The array is of the form [ backend, shaderIndex0, shaderIndex1, ... ] where each
// shader index is an active variant. Each bit in the activeVariants bitmask
// represents one of the possible variant combinations.
bool writeActiveInfo(const filaflat::ChunkContainer& package, backend::Backend backend,
VariantList activeVariants);
bool writeActiveInfo(const filaflat::ChunkContainer& package,
backend::ShaderLanguage shaderLanguage, VariantList activeVariants);
private:
utils::CString mJsonString;
+4 -1
View File
@@ -29,11 +29,13 @@ namespace matdbg {
// in a manner similar to ShaderExtractor.
class ShaderReplacer {
public:
ShaderReplacer(backend::Backend backend, const void* data, size_t size);
ShaderReplacer(backend::Backend backend, backend::ShaderLanguage language,
const void* data, size_t size);
~ShaderReplacer();
bool replaceShaderSource(backend::ShaderModel shaderModel, Variant variant,
backend::ShaderStage stage, const char* sourceString, size_t stringLength);
const uint8_t* getEditedPackage() const;
filamat::ChunkType getMaterialTag() const noexcept;
size_t getEditedSize() const;
private:
bool replaceSpirv(backend::ShaderModel shaderModel, Variant variant,
@@ -42,6 +44,7 @@ private:
filaflat::ChunkContainer mOriginalPackage;
filaflat::ChunkContainer* mEditedPackage = nullptr;
filamat::ChunkType mMaterialTag = filamat::ChunkType::Unknown;
filamat::ChunkType mDeleteTag = filamat::ChunkType::Unknown;
filamat::ChunkType mDictionaryTag = filamat::ChunkType::Unknown;
};
+16 -6
View File
@@ -86,6 +86,8 @@ bool ApiHandler::handleGetApiShader(struct mg_connection* conn,
}
std::string_view const glsl("glsl");
std::string_view const essl3("essl3");
std::string_view const essl1("essl1");
std::string_view const msl("msl");
std::string_view const spirv("spirv");
size_t const qlength = strlen(request->query_string);
@@ -109,12 +111,20 @@ bool ApiHandler::handleGetApiShader(struct mg_connection* conn,
}
if (glindex[0]) {
if (language != glsl) {
return softError("Only GLSL is supported.");
ChunkType chunkType;
ShaderLanguage shaderLanguage;
if (language == essl3) {
chunkType = ChunkType::MaterialGlsl;
shaderLanguage = ShaderLanguage::ESSL3;
} else if (language == essl1) {
chunkType = ChunkType::MaterialEssl1;
shaderLanguage = ShaderLanguage::ESSL1;
} else {
return softError("Only essl3 and essl1 are supported.");
}
FixedCapacityVector<ShaderInfo> info(getShaderCount(package, ChunkType::MaterialGlsl));
if (!getShaderInfo(package, info.data(), ChunkType::MaterialGlsl)) {
FixedCapacityVector<ShaderInfo> info(getShaderCount(package, chunkType));
if (!getShaderInfo(package, info.data(), chunkType)) {
return error(__LINE__, uri);
}
@@ -123,7 +133,7 @@ bool ApiHandler::handleGetApiShader(struct mg_connection* conn,
return error(__LINE__, uri);
}
ShaderExtractor extractor(ShaderLanguage::ESSL3, result->package, result->packageSize);
ShaderExtractor extractor(shaderLanguage, result->package, result->packageSize);
if (!extractor.parse()) {
return error(__LINE__, uri);
}
@@ -314,7 +324,7 @@ bool ApiHandler::handleGet(CivetServer* server, struct mg_connection* conn) {
return error(__LINE__, uri);
}
JsonWriter writer;
if (!writer.writeActiveInfo(package, mServer->mBackend, record.activeVariants)) {
if (!writer.writeActiveInfo(package, mServer->mShaderLanguage, record.activeVariants)) {
return error(__LINE__, uri);
}
bool const last = (++index) == mServer->mMaterialRecords.size();
+13 -36
View File
@@ -122,7 +122,8 @@ private:
DebugServer* mServer;
};
DebugServer::DebugServer(Backend backend, int port) : mBackend(backend) {
DebugServer::DebugServer(Backend backend, ShaderLanguage shaderLanguage, int port)
: mBackend(backend), mShaderLanguage(shaderLanguage) {
#if !SERVE_FROM_SOURCE_TREE
ASSET_MAP["/index.html"] = {
@@ -254,47 +255,23 @@ bool DebugServer::handleEditCommand(const MaterialKey& key, backend::Backend api
return error(__LINE__);
}
FixedCapacityVector<ShaderInfo> infos;
size_t shaderCount;
switch (api) {
case backend::Backend::OPENGL: {
shaderCount = getShaderCount(package, ChunkType::MaterialGlsl);
infos.reserve(shaderCount);
infos.resize(shaderCount);
if (!getShaderInfo(package, infos.data(), ChunkType::MaterialGlsl)) {
return error(__LINE__);
}
break;
}
case backend::Backend::VULKAN: {
shaderCount = getShaderCount(package, ChunkType::MaterialSpirv);
infos.reserve(shaderCount);
infos.resize(shaderCount);
if (!getShaderInfo(package, infos.data(), ChunkType::MaterialSpirv)) {
return error(__LINE__);
}
break;
}
case backend::Backend::METAL: {
shaderCount = getShaderCount(package, ChunkType::MaterialMetal);
infos.reserve(shaderCount);
infos.resize(shaderCount);
if (!getShaderInfo(package, infos.data(), ChunkType::MaterialMetal)) {
return error(__LINE__);
}
break;
}
default:
error(__LINE__);
}
ShaderReplacer editor(api, mShaderLanguage, package.getData(), package.getSize());
size_t shaderCount = getShaderCount(package, editor.getMaterialTag());
if (shaderIndex < 0 || shaderIndex >= shaderCount) {
return error(__LINE__);
}
FixedCapacityVector<ShaderInfo> infos;
infos.reserve(shaderCount);
infos.resize(shaderCount);
if (!getShaderInfo(package, infos.data(), editor.getMaterialTag())) {
return error(__LINE__);
}
const ShaderInfo info = infos[shaderIndex];
ShaderReplacer editor(api, package.getData(), package.getSize());
if (!editor.replaceShaderSource(info.shaderModel, info.variant, info.pipelineStage, source, size)) {
if (!editor.replaceShaderSource(info.shaderModel, info.variant, info.pipelineStage, source,
size)) {
return error(__LINE__);
}
+33 -16
View File
@@ -136,13 +136,22 @@ static void printShaderInfo(ostream& json, const vector<ShaderInfo>& info, const
}
}
static bool printGlslInfo(ostream& json, const ChunkContainer& container) {
static bool printGlslInfo(ostream& json, const ChunkContainer& container, ChunkType chunkType) {
std::vector<ShaderInfo> info;
info.resize(getShaderCount(container, ChunkType::MaterialGlsl));
if (!getShaderInfo(container, info.data(), ChunkType::MaterialGlsl)) {
info.resize(getShaderCount(container, chunkType));
if (!getShaderInfo(container, info.data(), chunkType)) {
return false;
}
json << "\"opengl\": [\n";
switch (chunkType) {
case ChunkType::MaterialEssl1:
json << "\"essl1\": [\n";
break;
case ChunkType::MaterialGlsl:
json << "\"opengl\": [\n";
break;
default:
assert(false); // unreachable
}
printShaderInfo(json, info, container);
json << "],\n";
return true;
@@ -180,7 +189,10 @@ bool JsonWriter::writeMaterialInfo(const filaflat::ChunkContainer& container) {
if (!printParametersInfo(json, container)) {
return false;
}
if (!printGlslInfo(json, container)) {
if (!printGlslInfo(json, container, ChunkType::MaterialGlsl)) {
return false;
}
if (!printGlslInfo(json, container, ChunkType::MaterialEssl1)) {
return false;
}
if (!printVkInfo(json, container)) {
@@ -220,29 +232,34 @@ size_t JsonWriter::getJsonSize() const {
}
bool JsonWriter::writeActiveInfo(const filaflat::ChunkContainer& package,
Backend backend, VariantList activeVariants) {
ShaderLanguage shaderLanguage, VariantList activeVariants) {
vector<ShaderInfo> shaders;
ostringstream json;
json << "[\"";
switch (backend) {
case Backend::OPENGL:
shaders.resize(getShaderCount(package, ChunkType::MaterialGlsl));
getShaderInfo(package, shaders.data(), ChunkType::MaterialGlsl);
ChunkType chunkType;
switch (shaderLanguage) {
case ShaderLanguage::ESSL1:
json << "essl1";
chunkType = ChunkType::MaterialEssl1;
break;
case ShaderLanguage::ESSL3:
json << "opengl";
chunkType = ChunkType::MaterialGlsl;
break;
case Backend::VULKAN:
shaders.resize(getShaderCount(package, ChunkType::MaterialSpirv));
getShaderInfo(package, shaders.data(), ChunkType::MaterialSpirv);
case ShaderLanguage::SPIRV:
json << "vulkan";
chunkType = ChunkType::MaterialSpirv;
break;
case Backend::METAL:
shaders.resize(getShaderCount(package, ChunkType::MaterialMetal));
getShaderInfo(package, shaders.data(), ChunkType::MaterialMetal);
case ShaderLanguage::MSL:
json << "metal";
chunkType = ChunkType::MaterialMetal;
break;
default:
return false;
}
shaders.resize(getShaderCount(package, chunkType));
getShaderInfo(package, shaders.data(), chunkType);
json << "\"";
for (size_t variant = 0; variant < activeVariants.size(); variant++) {
if (activeVariants[variant]) {
+26 -9
View File
@@ -94,22 +94,33 @@ private:
filaflat::BlobDictionary mDataBlobs;
};
ShaderReplacer::ShaderReplacer(Backend backend, const void* data, size_t size) :
ShaderReplacer::ShaderReplacer(Backend backend, ShaderLanguage language,
const void* data, size_t size) :
mBackend(backend), mOriginalPackage(data, size) {
switch (backend) {
case Backend::OPENGL:
mMaterialTag = ChunkType::MaterialGlsl;
switch (language) {
// ESSL1 and ESSL3 share the same dictionary, and replacing either will corrupt the other.
// If replacing one, delete both.
case backend::ShaderLanguage::ESSL1:
mMaterialTag = ChunkType::MaterialEssl1;
mDeleteTag = ChunkType::MaterialGlsl;
mDictionaryTag = ChunkType::DictionaryText;
break;
case Backend::METAL:
case backend::ShaderLanguage::ESSL3:
mMaterialTag = ChunkType::MaterialGlsl;
mDeleteTag = ChunkType::MaterialEssl1;
mDictionaryTag = ChunkType::DictionaryText;
break;
case backend::ShaderLanguage::MSL:
mMaterialTag = ChunkType::MaterialMetal;
mDictionaryTag = ChunkType::DictionaryText;
break;
case Backend::VULKAN:
case backend::ShaderLanguage::SPIRV:
mMaterialTag = ChunkType::MaterialSpirv;
mDictionaryTag = ChunkType::DictionarySpirv;
break;
default:
case backend::ShaderLanguage::METAL_LIBRARY:
mMaterialTag = ChunkType::MaterialMetalLibrary;
mDictionaryTag = ChunkType::DictionaryMetalLibrary;
break;
}
}
@@ -133,7 +144,7 @@ bool ShaderReplacer::replaceShaderSource(ShaderModel shaderModel, Variant varian
return replaceSpirv(shaderModel, variant, stage, sourceString, stringLength);
}
// Clone all chunks except Dictionary* and Material*.
// Clone (almost) all chunks except Dictionary* and Material*.
stringstream sstream(std::string((const char*) cc.getData(), cc.getSize()));
stringstream tstream;
{
@@ -145,7 +156,9 @@ bool ShaderReplacer::replaceShaderSource(ShaderModel shaderModel, Variant varian
sstream.read((char*) &size, sizeof(size));
content.resize(size);
sstream.read((char*) content.data(), size);
if (ChunkType(type) == mDictionaryTag|| ChunkType(type) == mMaterialTag) {
if (ChunkType(type) == mDictionaryTag
|| ChunkType(type) == mDeleteTag
|| ChunkType(type) == mMaterialTag) {
continue;
}
tstream.write((char*) &type, sizeof(type));
@@ -297,6 +310,10 @@ size_t ShaderReplacer::getEditedSize() const {
return mEditedPackage->getSize();
}
filamat::ChunkType ShaderReplacer::getMaterialTag() const noexcept {
return mMaterialTag;
}
ShaderIndex::ShaderIndex(ChunkType dictTag, ChunkType matTag, const filaflat::ChunkContainer& cc) :
mDictTag(dictTag), mMatTag(matTag) {
+5 -1
View File
@@ -30,6 +30,7 @@ async function fetchShaderCode(matid, backend, language, index) {
let query;
switch (backend) {
case "opengl":
case "essl1":
query = `type=${language}&glindex=${index}`;
break;
case "vulkan":
@@ -82,7 +83,10 @@ async function queryActiveShaders() {
function rebuildMaterial(materialId, backend, shaderIndex, editedText) {
let api = 0;
switch (backend) {
case "opengl": api = 1; break;
case "opengl":
case "essl1":
api = 1;
break;
case "vulkan": api = 2; break;
case "metal": api = 3; break;
}
+11 -4
View File
@@ -20,11 +20,19 @@ const kUntitledPlaceholder = "untitled";
// Maps to backend to the languages allowed for that backend.
const LANGUAGE_CHOICES = {
'opengl': ['glsl'],
'opengl': ['essl3', 'essl1'],
'essl1': ['essl3', 'essl1'],
'vulkan': ['glsl', 'spirv'],
'metal': ['msl'],
};
const DEFAULT_LANGUAGE_FOR_BACKEND = {
'opengl': 'essl3',
'essl1': 'essl1',
'vulkan': 'glsl',
'metal': 'msl',
};
const BACKENDS = Object.keys(LANGUAGE_CHOICES);
const MATERIAL_INFO_KEY_TO_STRING = {
@@ -1051,9 +1059,8 @@ class MatdbgViewer extends LitElement {
updated(props) {
// Set a language if there hasn't been one set.
if (props.has('currentBackend') && this.currentBackend) {
const choices = LANGUAGE_CHOICES[this.currentBackend];
if (choices.indexOf(this.currentLanguage) < 0) {
this.currentLanguage = choices[0];
if (LANGUAGE_CHOICES[this.currentBackend].indexOf(this.currentLanguage) < 0) {
this.currentLanguage = DEFAULT_LANGUAGE_FOR_BACKEND[this.currentBackend];
}
}
if (props.has('currentMaterial')) {
+1 -1
View File
@@ -146,8 +146,8 @@ int main(int argc, char** argv) {
auto cleanup = [&app](Engine* engine, View*, Scene*) {
engine->destroy(app.light);
engine->destroy(app.materialInstance);
engine->destroy(app.mesh.renderable);
engine->destroy(app.materialInstance);
engine->destroy(app.material);
};
+4 -4
View File
@@ -218,7 +218,7 @@ int main(int argc, char** argv) {
.depth(eyeCount)
.levels(1)
.sampler(Texture::Sampler::SAMPLER_2D_ARRAY)
.format(Texture::InternalFormat::DEPTH24)
.format(Texture::InternalFormat::DEPTH32F)
.usage(Texture::Usage::DEPTH_ATTACHMENT)
.build(*engine);
app.stereoRenderTarget = RenderTarget::Builder()
@@ -324,12 +324,12 @@ int main(int argc, char** argv) {
auto& em = utils::EntityManager::get();
for (MaterialInstance* mi : app.quadMatInstances) {
engine->destroy(mi);
}
for (utils::Entity e : app.quadEntities) {
engine->destroy(e);
}
for (MaterialInstance* mi : app.quadMatInstances) {
engine->destroy(mi);
}
engine->destroy(app.quadMaterial);
engine->destroy(app.quadIb);
engine->destroy(app.quadVb);
+3 -3
View File
@@ -209,7 +209,7 @@ int main(int argc, char** argv) {
app.offscreenDepthTexture = Texture::Builder()
.width(vp.width).height(vp.height).levels(1)
.usage(Texture::Usage::DEPTH_ATTACHMENT)
.format(Texture::InternalFormat::DEPTH24).build(*engine);
.format(Texture::InternalFormat::DEPTH32F).build(*engine);
app.offscreenRenderTarget = RenderTarget::Builder()
.texture(RenderTarget::AttachmentPoint::COLOR, app.offscreenColorTexture)
.texture(RenderTarget::AttachmentPoint::DEPTH, app.offscreenDepthTexture)
@@ -321,11 +321,11 @@ int main(int argc, char** argv) {
engine->destroy(app.reflectedMonkey);
engine->destroy(app.lightEntity);
engine->destroy(app.quadEntity);
engine->destroy(app.meshMatInstance);
engine->destroy(app.meshMaterial);
engine->destroy(app.monkeyMesh.renderable);
engine->destroy(app.monkeyMesh.vertexBuffer);
engine->destroy(app.monkeyMesh.indexBuffer);
engine->destroy(app.meshMatInstance);
engine->destroy(app.meshMaterial);
engine->destroy(app.offscreenColorTexture);
engine->destroy(app.offscreenDepthTexture);
engine->destroy(app.offscreenRenderTarget);
+9 -9
View File
@@ -639,6 +639,15 @@ int main(int argc, char** argv) {
};
auto cleanup = [&app](Engine* engine, View*, Scene*) {
for (auto i = 0; i < 4; i++) {
engine->destroy(app.renderables[i]);
}
for (auto i = 0; i < app.boCount; i++) {
engine->destroy(app.bos[i]);
}
for (auto i = 0; i < app.vbCount; i++) {
engine->destroy(app.vbs[i]);
}
engine->destroy(app.skybox);
engine->destroy(app.mat);
engine->destroy(app.ib);
@@ -648,15 +657,6 @@ int main(int argc, char** argv) {
engine->destroy(app.mt);
engine->destroyCameraComponent(app.camera);
EntityManager::get().destroy(app.camera);
for (auto i = 0; i < app.vbCount; i++) {
engine->destroy(app.vbs[i]);
}
for ( auto i = 0; i < app.boCount; i++) {
engine->destroy(app.bos[i]);
}
for ( auto i = 0; i < 4; i++) {
engine->destroy(app.renderables[i]);
}
};
FilamentApp::get().animate([&app](Engine* engine, View* view, double now) {
+1 -1
View File
@@ -199,8 +199,8 @@ int main(int argc, char** argv) {
};
auto cleanup = [&app](Engine* engine, View*, Scene*) {
engine->destroy(app.materialInstance);
engine->destroy(app.mesh.renderable);
engine->destroy(app.materialInstance);
engine->destroy(app.material);
engine->destroy(app.albedo);
engine->destroy(app.normal);
+36 -35
View File
@@ -11,48 +11,49 @@ endif()
# Sources and headers
# ==================================================================================================
set(SHADERS
src/ambient_occlusion.fs
src/brdf.fs
src/surface_ambient_occlusion.fs
src/surface_brdf.fs
src/common_defines.glsl
src/common_getters.glsl
src/common_instancing.glsl
src/surface_instancing.glsl
src/common_graphics.fs
src/common_lighting.fs
src/common_material.fs
src/surface_lighting.fs
src/surface_material.fs
src/common_math.glsl
src/common_shading.fs
src/common_shadowing.glsl
src/common_types.glsl
src/depth_main.fs
src/fog.fs
src/getters.cs
src/getters.fs
src/getters.vs
src/light_directional.fs
src/light_indirect.fs
src/light_reflections.fs
src/light_punctual.fs
src/main.cs
src/main.fs
src/main.vs
src/material_inputs.fs
src/material_inputs.vs
src/post_process.fs
src/post_process.vs
src/common_varyings.glsl
src/surface_shadowing.glsl
src/surface_types.glsl
src/surface_depth_main.fs
src/surface_fog.fs
src/surface_getters.cs
src/surface_getters.fs
src/surface_getters.vs
src/surface_light_directional.fs
src/surface_light_indirect.fs
src/surface_light_reflections.fs
src/surface_light_punctual.fs
src/surface_main.cs
src/surface_main.fs
src/surface_main.vs
src/surface_material_inputs.fs
src/surface_material_inputs.vs
src/post_process_main.fs
src/post_process_main.vs
src/post_process_getters.vs
src/post_process_inputs.fs
src/post_process_inputs.vs
src/shading_lit.fs
src/shading_lit_custom.fs
src/shading_model_cloth.fs
src/shading_model_standard.fs
src/shading_model_subsurface.fs
src/shading_parameters.fs
src/shading_reflections.fs
src/shading_unlit.fs
src/shadowing.fs
src/varyings.glsl
src/vignette.fs
src/surface_shading_lit.fs
src/surface_shading_lit_custom.fs
src/surface_shading_model_cloth.fs
src/surface_shading_model_standard.fs
src/surface_shading_model_subsurface.fs
src/surface_shading_parameters.fs
src/surface_shading_reflections.fs
src/surface_shading_unlit.fs
src/surface_shadowing.fs
src/surface_varyings.glsl
src/inline_vignette.fs
)
# These files aren't part of libshaders, but are included by materials inside
@@ -60,7 +61,7 @@ set(SHADERS
#
# tone_mapping.fs
# conversion_functions.fs
# dithering.fs
# inline_dithering.fs
set(MINIFIED_DIR ${CMAKE_CURRENT_BINARY_DIR}/minified)
+34
View File
@@ -0,0 +1,34 @@
# Shader Code Directory
This directory contains GLSL (OpenGL Shading Language) code snippets, organized by their function and stage in the graphics pipeline. These snippets are designed to be used as **building blocks** by the **Shader Generator** within this project. Instead of being compiled directly, these snippets are combined and processed to generate complete, functional shader programs for various purposes.
## File Naming Convention
Shader files within this directory follow a consistent naming convention to easily identify their purpose and usage:
`prefix_name.suffix`
### Prefixes
The prefix indicates the domain or category of the shader code:
* **`surface`:** Snippets with this prefix are intended for use in **surface shaders**. Surface shaders define the visual properties of object surfaces, handling aspects like lighting, texturing, and material properties.
* **`post_process`:** Snippets with this prefix are used in **post-processing shaders**. Post-processing shaders operate on the entire rendered image after the main rendering pass to achieve effects such as blur, bloom, color correction, and more.
* **`common`:** Snippets with this prefix contain **shared code** that can be used by **both** `surface` and `post_process` shaders. This includes utility functions, common data structures, and reusable logic, promoting modularity and reducing code duplication.
* **`inline`:** Snippets with this prefix are **specifically designed to be directly included within other shader files** during the generation process. They often contain reusable functions or macros that need to be present in the final shader code but not necessarily categorized as `surface` or `post_process`.
### Suffixes (Extensions)
The suffix (file extension) specifies the **shader stage** that the code snippet is intended for:
* **`.vs`:** Files with this extension contain code snippets for **vertex shaders**. Vertex shaders operate on individual vertices and are typically used to transform vertex positions, calculate normals, and pass data to the fragment shader.
* **`.fs`:** Files with this extension contain code snippets for **fragment shaders**. Fragment shaders, also known as pixel shaders, determine the final color of each pixel. They are used for lighting, texturing, and other per-pixel operations.
* **`.cs`:** Files with this extension contain code snippets for **compute shaders**. Compute shaders are used for general-purpose computation on the GPU, outside the traditional rendering pipeline. They can be used for tasks like physics simulations, image processing, and more. (Currently not implemented yet)
* **`.glsl`:** Files with this extension contain **reusable GLSL code snippets, including functions, structures, or constants**, that are intended to be included or linked into multiple shader stages (vertex, fragment, or compute). This is a generic extension to signify that the file does not belong exclusively to a single shader stage.
## Example
* `surface_light_directional.fs`: Fragment shader snippets for objects using the directional lighting model.
* `post_process_getters.vs`: Vertex shader snippets containing reusable getter functions for post-processing shaders.
* `common_math.glsl`: GLSL code with reusable math constants and functions shared by both surface and post-processing shaders.
+1 -1
View File
@@ -28,7 +28,7 @@ highp mat4 getClipFromWorldMatrix() {
int eye = instance_index % CONFIG_STEREO_EYE_COUNT;
return frameUniforms.clipFromWorldMatrix[eye];
#elif defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_MULTIVIEW)
return frameUniforms.clipFromWorldMatrix[gl_ViewID_OVR];
return frameUniforms.clipFromWorldMatrix[filament_multiview_data.y];
#else
return frameUniforms.clipFromWorldMatrix[0];
#endif
+16
View File
@@ -0,0 +1,16 @@
//------------------------------------------------------------------------------
// Common Varyings
//------------------------------------------------------------------------------
// The `filament_multiview_data` variable is to pass the current state of multiview set in the
// vertex shader to the fragment shader. `x` means whether multiview is used, `y` means the current
// view index. Neither the multiview feature nor the `flat` keyword is supported in FL0. So, for
// FL0, declare it as a non-flat and non-varying variable and set it to zeros as a placeholder.
// `MATERIAL_FEATURE_LEVEL > 0` is used as a workaround instead of `defined(VARIANT_HAS_STEREO)` to
// make this line available for post-processing where we cannot use VARIANT_HAS_STEREO. The
// downside of this approach is that `flat VARYING` is used for non-STE shaders as well.
#if MATERIAL_FEATURE_LEVEL > 0 && defined(FILAMENT_STEREO_MULTIVIEW)
LAYOUT_LOCATION(12) flat VARYING ivec2 filament_multiview_data;
#else
ivec2 filament_multiview_data = ivec2(0, 0);
#endif

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