Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf75b4489b | ||
|
|
923ac98ea8 | ||
|
|
4fe852e88a | ||
|
|
864529254e | ||
|
|
93fa55bd29 | ||
|
|
fb9518e915 | ||
|
|
b780cb36d0 | ||
|
|
62cd8f1d35 | ||
|
|
793f2b4eb7 | ||
|
|
9a2ca8ddbb | ||
|
|
67710723d7 | ||
|
|
40851f4b51 | ||
|
|
87bdf96449 |
@@ -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
|
||||
|
||||
@@ -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,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.
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
+4
-64
@@ -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
|
||||
+8
-196
@@ -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
|
||||
+38
-4
@@ -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;
|
||||
+13
-21
@@ -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
|
||||
+6
-64
@@ -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
|
||||
+8
-7
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(){}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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__);
|
||||
}
|
||||
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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
@@ -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')) {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user