Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9f4433324 | ||
|
|
05cdeccc27 | ||
|
|
ad4f349f00 | ||
|
|
06a2def85f | ||
|
|
a04019937e | ||
|
|
fff7bd2b28 | ||
|
|
3c4591df17 | ||
|
|
4fe852e88a | ||
|
|
864529254e | ||
|
|
93fa55bd29 | ||
|
|
fb9518e915 | ||
|
|
b780cb36d0 | ||
|
|
62cd8f1d35 | ||
|
|
793f2b4eb7 | ||
|
|
9a2ca8ddbb | ||
|
|
67710723d7 | ||
|
|
40851f4b51 | ||
|
|
87bdf96449 |
+17
-10
@@ -667,10 +667,6 @@ function(list_licenses OUTPUT MODULES)
|
||||
endfunction()
|
||||
|
||||
set(COMBINE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/build/linux/combine-static-libs.sh")
|
||||
if (WIN32)
|
||||
set(COMBINE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/build/windows/combine-static-libs.bat")
|
||||
set(CMAKE_AR "lib.exe")
|
||||
endif()
|
||||
|
||||
# Add a custom command to TARGET that combines the static libraries in DEPS into a single archive.
|
||||
function(combine_static_libs TARGET OUTPUT DEPS)
|
||||
@@ -685,12 +681,22 @@ function(combine_static_libs TARGET OUTPUT DEPS)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${TARGET} POST_BUILD
|
||||
COMMAND "${COMBINE_SCRIPT}" "${CMAKE_AR}" "${OUTPUT}" ${DEPS_FILES}
|
||||
COMMENT "Combining ${target} dependencies into single shared library"
|
||||
VERBATIM
|
||||
)
|
||||
if (WIN32)
|
||||
add_custom_command(
|
||||
TARGET ${TARGET} POST_BUILD
|
||||
COMMAND lib.exe /nologo /out:temp.lib ${DEPS_FILES}
|
||||
COMMAND "${CMAKE_COMMAND}" -E rename temp.lib ${OUTPUT}
|
||||
COMMENT "Combining ${target} dependencies into single shared library"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_command(
|
||||
TARGET ${TARGET} POST_BUILD
|
||||
COMMAND "${COMBINE_SCRIPT}" "${CMAKE_AR}" "${OUTPUT}" ${DEPS_FILES}
|
||||
COMMENT "Combining ${target} dependencies into single shared library"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ==================================================================================================
|
||||
@@ -761,6 +767,7 @@ add_subdirectory(${LIBRARIES}/utils)
|
||||
add_subdirectory(${LIBRARIES}/viewer)
|
||||
add_subdirectory(${FILAMENT}/filament)
|
||||
add_subdirectory(${FILAMENT}/shaders)
|
||||
add_subdirectory(${EXTERNAL}/abseil/tnt)
|
||||
add_subdirectory(${EXTERNAL}/basisu/tnt)
|
||||
add_subdirectory(${EXTERNAL}/civetweb/tnt)
|
||||
add_subdirectory(${EXTERNAL}/imgui/tnt)
|
||||
|
||||
@@ -7,3 +7,6 @@ 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
|
||||
- backend: New platform API to better handle external textures [⚠️ **New Material Version**]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
@echo off
|
||||
set selfName=%0
|
||||
|
||||
:: Check that we have at least 3 arguments.
|
||||
set argC=0
|
||||
for %%x in (%*) do Set /A argC+=1
|
||||
if %argC% LSS 3 goto :print_help
|
||||
|
||||
set AR_TOOL=%1
|
||||
shift
|
||||
set OUTPUT_PATH=%1
|
||||
shift
|
||||
|
||||
set ARCHIVES=
|
||||
:loop
|
||||
if [%1]==[] goto :finished
|
||||
set ARCHIVES=%ARCHIVES% %1
|
||||
shift
|
||||
goto :loop
|
||||
|
||||
:finished
|
||||
|
||||
%AR_TOOL% /nologo /out:%OUTPUT_PATH% %ARCHIVES% || goto :error
|
||||
|
||||
exit /B %ERRORLEVEL%
|
||||
|
||||
:print_help
|
||||
echo %selfName%. Combine multiple static libraries using an archiver tool.
|
||||
echo;
|
||||
echo Usage:
|
||||
echo %selfName% ^<path-to-ar^> ^<output-archive^> ^<archives^>...
|
||||
echo;
|
||||
echo Notes:
|
||||
echo ^<archives^> must be a list of absolute paths to static library archives.
|
||||
echo This script creates a temporary working directory inside the current directory.
|
||||
exit /B 1
|
||||
|
||||
:error
|
||||
exit /B %ERRORLEVEL%
|
||||
@@ -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,
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class Driver;
|
||||
@@ -41,6 +43,46 @@ public:
|
||||
struct Fence {};
|
||||
struct Stream {};
|
||||
|
||||
class ExternalImageHandle;
|
||||
|
||||
class ExternalImage {
|
||||
friend class ExternalImageHandle;
|
||||
std::atomic_uint32_t mRefCount{0};
|
||||
protected:
|
||||
virtual ~ExternalImage() noexcept;
|
||||
};
|
||||
|
||||
class ExternalImageHandle {
|
||||
ExternalImage* UTILS_NULLABLE mTarget = nullptr;
|
||||
static void incref(ExternalImage* UTILS_NULLABLE p) noexcept;
|
||||
static void decref(ExternalImage* UTILS_NULLABLE p) noexcept;
|
||||
|
||||
public:
|
||||
ExternalImageHandle() noexcept;
|
||||
~ExternalImageHandle() noexcept;
|
||||
explicit ExternalImageHandle(ExternalImage* UTILS_NULLABLE p) noexcept;
|
||||
ExternalImageHandle(ExternalImageHandle const& rhs) noexcept;
|
||||
ExternalImageHandle(ExternalImageHandle&& rhs) noexcept;
|
||||
ExternalImageHandle& operator=(ExternalImageHandle const& rhs) noexcept;
|
||||
ExternalImageHandle& operator=(ExternalImageHandle&& rhs) noexcept;
|
||||
|
||||
explicit operator bool() const noexcept { return mTarget != nullptr; }
|
||||
|
||||
ExternalImage* UTILS_NULLABLE get() noexcept { return mTarget; }
|
||||
ExternalImage const* UTILS_NULLABLE get() const noexcept { return mTarget; }
|
||||
|
||||
ExternalImage* UTILS_NULLABLE operator->() noexcept { return mTarget; }
|
||||
ExternalImage const* UTILS_NULLABLE operator->() const noexcept { return mTarget; }
|
||||
|
||||
ExternalImage& operator*() noexcept { return *mTarget; }
|
||||
ExternalImage const& operator*() const noexcept { return *mTarget; }
|
||||
|
||||
void clear() noexcept;
|
||||
void reset(ExternalImage* UTILS_NULLABLE p) noexcept;
|
||||
};
|
||||
|
||||
using ExternalImageHandleRef = ExternalImageHandle const&;
|
||||
|
||||
/**
|
||||
* The type of technique for stereoscopic rendering. (Note that the materials used will need to
|
||||
* be compatible with the chosen technique.)
|
||||
|
||||
@@ -51,10 +51,9 @@ protected:
|
||||
~OpenGLPlatform() noexcept override;
|
||||
|
||||
public:
|
||||
|
||||
struct ExternalTexture {
|
||||
unsigned int target; // GLenum target
|
||||
unsigned int id; // GLuint id
|
||||
unsigned int target; // GLenum target
|
||||
unsigned int id; // GLuint id
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -324,36 +323,45 @@ public:
|
||||
* Destroys an external texture handle and associated data.
|
||||
* @param texture a pointer to the handle to destroy.
|
||||
*/
|
||||
virtual void destroyExternalImage(ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
virtual void destroyExternalImageTexture(ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
|
||||
// called on the application thread to allow Filament to take ownership of the image
|
||||
|
||||
/**
|
||||
* Takes ownership of the externalImage. The externalImage parameter depends on the Platform's
|
||||
* concrete implementation. Ownership is released when destroyExternalImage() is called.
|
||||
* concrete implementation. Ownership is released when destroyExternalImageTexture() is called.
|
||||
*
|
||||
* WARNING: This is called synchronously from the application thread (NOT the Driver thread)
|
||||
*
|
||||
* @param externalImage A token representing the platform's external image.
|
||||
* @see destroyExternalImage
|
||||
* @{
|
||||
*/
|
||||
virtual void retainExternalImage(void* UTILS_NONNULL externalImage) noexcept;
|
||||
|
||||
virtual void retainExternalImage(ExternalImageHandleRef externalImage) noexcept;
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* Called to bind the platform-specific externalImage to an ExternalTexture.
|
||||
* ExternalTexture::id is guaranteed to be bound when this method is called and ExternalTexture
|
||||
* is updated with new values for id/target if necessary.
|
||||
*
|
||||
* WARNING: this method is not allowed to change the bound texture, or must restore the previous
|
||||
* binding upon return. This is to avoid problem with a backend doing state caching.
|
||||
* binding upon return. This is to avoid a problem with a backend doing state caching.
|
||||
*
|
||||
* @param externalImage The platform-specific external image.
|
||||
* @param texture an in/out pointer to ExternalTexture, id and target can be updated if necessary.
|
||||
* @return true on success, false on error.
|
||||
* @{
|
||||
*/
|
||||
virtual bool setExternalImage(void* UTILS_NONNULL externalImage,
|
||||
ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
|
||||
virtual bool setExternalImage(ExternalImageHandleRef externalImage,
|
||||
ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* The method allows platforms to convert a user-supplied external image object into a new type
|
||||
* (e.g. HardwareBuffer => EGLImage). The default implementation returns source.
|
||||
|
||||
@@ -34,12 +34,14 @@ public:
|
||||
PlatformCocoaGL();
|
||||
~PlatformCocoaGL() noexcept override;
|
||||
|
||||
ExternalImageHandle createExternalImage(void* cvPixelBuffer) noexcept;
|
||||
|
||||
protected:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const DriverConfig& driverConfig) noexcept override;
|
||||
|
||||
// Currently returns 0
|
||||
int getOSVersion() const noexcept override;
|
||||
@@ -59,10 +61,12 @@ protected:
|
||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
||||
void commit(SwapChain* swapChain) noexcept override;
|
||||
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImage(ExternalTexture* texture) noexcept override;
|
||||
ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
|
||||
void retainExternalImage(void* externalImage) noexcept override;
|
||||
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
|
||||
void retainExternalImage(ExternalImageHandleRef externalImage) noexcept override;
|
||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||
|
||||
private:
|
||||
PlatformCocoaGLImpl* pImpl = nullptr;
|
||||
|
||||
@@ -32,11 +32,13 @@ public:
|
||||
PlatformCocoaTouchGL();
|
||||
~PlatformCocoaTouchGL() noexcept override;
|
||||
|
||||
ExternalImageHandle createExternalImage(void* cvPixelBuffer) noexcept;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedGLContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const DriverConfig& driverConfig) noexcept override;
|
||||
|
||||
int getOSVersion() const noexcept final { return 0; }
|
||||
|
||||
@@ -56,10 +58,12 @@ public:
|
||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
||||
void commit(SwapChain* swapChain) noexcept override;
|
||||
|
||||
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImage(ExternalTexture* texture) noexcept override;
|
||||
ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
|
||||
void retainExternalImage(void* externalImage) noexcept override;
|
||||
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
|
||||
void retainExternalImage(ExternalImageHandleRef externalImage) noexcept override;
|
||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||
|
||||
private:
|
||||
PlatformCocoaTouchGLImpl* pImpl = nullptr;
|
||||
|
||||
@@ -47,6 +47,11 @@ public:
|
||||
// Return true if we're on an OpenGL platform (as opposed to OpenGL ES). false by default.
|
||||
virtual bool isOpenGL() const noexcept;
|
||||
|
||||
/**
|
||||
* Creates an ExternalImage from a EGLImageKHR
|
||||
*/
|
||||
ExternalImageHandle createExternalImage(EGLImageKHR eglImage) noexcept;
|
||||
|
||||
protected:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Helper for EGL configs and attributes parameters
|
||||
@@ -118,9 +123,10 @@ protected:
|
||||
void destroyFence(Fence* fence) noexcept override;
|
||||
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept override;
|
||||
|
||||
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImage(ExternalTexture* texture) noexcept override;
|
||||
ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
|
||||
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
|
||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||
|
||||
/**
|
||||
* Logs glGetError() to slog.e
|
||||
@@ -188,6 +194,12 @@ protected:
|
||||
|
||||
void initializeGlExtensions() noexcept;
|
||||
|
||||
struct ExternalImageEGL : public ExternalImage {
|
||||
EGLImageKHR eglImage = EGL_NO_IMAGE;
|
||||
protected:
|
||||
~ExternalImageEGL() override;
|
||||
};
|
||||
|
||||
protected:
|
||||
EGLConfig findSwapChainConfig(uint64_t flags, bool window, bool pbuffer) const;
|
||||
|
||||
|
||||
@@ -57,6 +57,11 @@ protected:
|
||||
Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
|
||||
/**
|
||||
* Creates an ExternalImage from a EGLImageKHR
|
||||
*/
|
||||
ExternalImageHandle createExternalImage(AHardwareBuffer const *buffer, bool sRGB) noexcept;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// OpenGLPlatform Interface
|
||||
|
||||
@@ -89,6 +94,15 @@ protected:
|
||||
*/
|
||||
AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept override;
|
||||
|
||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||
|
||||
struct ExternalImageEGLAndroid : public ExternalImageEGL {
|
||||
AHardwareBuffer* aHardwareBuffer = nullptr;
|
||||
bool sRGB = false;
|
||||
protected:
|
||||
~ExternalImageEGLAndroid() override;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool makeCurrent(ContextType type,
|
||||
SwapChain* drawSwapChain,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -213,6 +215,14 @@ DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureViewSwizzle,
|
||||
backend::TextureSwizzle, b,
|
||||
backend::TextureSwizzle, a)
|
||||
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage2,
|
||||
backend::SamplerType, target,
|
||||
backend::TextureFormat, format,
|
||||
uint32_t, width,
|
||||
uint32_t, height,
|
||||
backend::TextureUsage, usage,
|
||||
backend::Platform::ExternalImageHandleRef, image)
|
||||
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage,
|
||||
backend::SamplerType, target,
|
||||
backend::TextureFormat, format,
|
||||
@@ -353,6 +363,7 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthClampSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxUniformBufferSize)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage2, backend::Platform::ExternalImageHandleRef, image)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage, void*, image)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(backend::TimerQueryResult, getTimerQueryValue, backend::TimerQueryHandle, query, uint64_t*, elapsedTime)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isWorkaroundNeeded, backend::Workaround, workaround)
|
||||
@@ -533,7 +544,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;
|
||||
};
|
||||
|
||||
@@ -16,8 +16,93 @@
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
void Platform::ExternalImageHandle::incref(ExternalImage* p) noexcept {
|
||||
if (p) {
|
||||
// incrementing the ref-count doesn't acquire or release anything
|
||||
p->mRefCount.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
void Platform::ExternalImageHandle::decref(ExternalImage* p) noexcept {
|
||||
if (p) {
|
||||
// When decrementing the ref-count, unless it reaches zero, there is no need to acquire data; we need to
|
||||
// release all previous writes though so they can be visible to the thread that will actually delete the
|
||||
// object.
|
||||
if (p->mRefCount.fetch_sub(1, std::memory_order_release) == 1) {
|
||||
// if we reach zero, we're about to delete the object, we need to acquire all previous writes from other
|
||||
// threads (i.e.: the memory from other threads prior to the decref() need to be visible now.
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle::ExternalImageHandle() noexcept = default;
|
||||
|
||||
Platform::ExternalImageHandle::~ExternalImageHandle() noexcept {
|
||||
decref(mTarget);
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImage* p) noexcept
|
||||
: mTarget(p) {
|
||||
incref(mTarget);
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImageHandle const& rhs) noexcept
|
||||
: mTarget(rhs.mTarget) {
|
||||
incref(mTarget);
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImageHandle&& rhs) noexcept
|
||||
: mTarget(rhs.mTarget) {
|
||||
rhs.mTarget = nullptr;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(ExternalImageHandle const& rhs) noexcept {
|
||||
if (UTILS_LIKELY(this != &rhs)) {
|
||||
incref(rhs.mTarget);
|
||||
decref(mTarget);
|
||||
mTarget = rhs.mTarget;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(ExternalImageHandle&& rhs) noexcept {
|
||||
if (UTILS_LIKELY(this != &rhs)) {
|
||||
decref(mTarget);
|
||||
mTarget = rhs.mTarget;
|
||||
rhs.mTarget = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Platform::ExternalImageHandle::clear() noexcept {
|
||||
decref(mTarget);
|
||||
mTarget = nullptr;
|
||||
}
|
||||
|
||||
void Platform::ExternalImageHandle::reset(ExternalImage* p) noexcept {
|
||||
incref(p);
|
||||
decref(mTarget);
|
||||
mTarget = p;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Platform::ExternalImage::~ExternalImage() noexcept = default;
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Platform::Platform() noexcept = default;
|
||||
|
||||
// this generates the vtable in this translation unit
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -513,6 +513,14 @@ void MetalDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTextu
|
||||
mContext->textures.insert(construct_handle<MetalTexture>(th, *mContext, src, r, g, b, a));
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImage2R(Handle<HwTexture> th,
|
||||
backend::SamplerType target,
|
||||
backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef image) {
|
||||
// FIXME: implement createTextureExternalImage2R
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th,
|
||||
backend::SamplerType target,
|
||||
backend::TextureFormat format,
|
||||
@@ -747,6 +755,10 @@ Handle<HwTexture> MetalDriver::createTextureViewSwizzleS() noexcept {
|
||||
return alloc_handle<MetalTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> MetalDriver::createTextureExternalImage2S() noexcept {
|
||||
return alloc_handle<MetalTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> MetalDriver::createTextureExternalImageS() noexcept {
|
||||
return alloc_handle<MetalTexture>();
|
||||
}
|
||||
@@ -947,6 +959,10 @@ ShaderModel MetalDriver::getShaderModel() const noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
ShaderLanguage MetalDriver::getShaderLanguage() const noexcept {
|
||||
return ShaderLanguage::MSL;
|
||||
}
|
||||
|
||||
Handle<HwStream> MetalDriver::createStreamNative(void* stream) {
|
||||
return {};
|
||||
}
|
||||
@@ -1135,8 +1151,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 };
|
||||
}
|
||||
|
||||
@@ -1214,6 +1230,10 @@ void MetalDriver::update3DImage(Handle<HwTexture> th, uint32_t level,
|
||||
th.getId(), level, xoffset, yoffset, zoffset, width, height, depth);
|
||||
}
|
||||
|
||||
void MetalDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
// FIXME: implement setupExternalImage2
|
||||
}
|
||||
|
||||
void MetalDriver::setupExternalImage(void* image) {
|
||||
// setupExternalImage is called on the Filament thread when creating a Texture or SwapChain from
|
||||
// a CVPixelBuffer external image. Here we take ownership of the passed in buffer by calling
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
#include "noop/NoopDriver.h"
|
||||
#include "CommandStreamDispatcher.h"
|
||||
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
Driver* NoopDriver::create() {
|
||||
@@ -39,6 +43,10 @@ ShaderModel NoopDriver::getShaderModel() const noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
ShaderLanguage NoopDriver::getShaderLanguage() const noexcept {
|
||||
return ShaderLanguage::ESSL3;
|
||||
}
|
||||
|
||||
// explicit instantiation of the Dispatcher
|
||||
template class ConcreteDispatcher<NoopDriver>;
|
||||
|
||||
@@ -258,6 +266,9 @@ void NoopDriver::update3DImage(Handle<HwTexture> th,
|
||||
scheduleDestroy(std::move(data));
|
||||
}
|
||||
|
||||
void NoopDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
}
|
||||
|
||||
void NoopDriver::setupExternalImage(void* image) {
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
|
||||
private:
|
||||
ShaderModel getShaderModel() const noexcept final;
|
||||
ShaderLanguage getShaderLanguage() const noexcept final;
|
||||
|
||||
uint64_t nextFakeHandle = 1;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_GLUTILS_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
@@ -25,6 +26,8 @@
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gl_headers.h"
|
||||
@@ -50,7 +53,7 @@ void assertFramebufferStatus(utils::io::ostream& out, GLenum target, const char*
|
||||
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target) { GLUtils::checkFramebufferStatus(out, target, __func__, __LINE__); }
|
||||
#endif
|
||||
|
||||
constexpr inline GLuint getComponentCount(ElementType type) noexcept {
|
||||
constexpr GLuint getComponentCount(ElementType type) noexcept {
|
||||
using ElementType = ElementType;
|
||||
switch (type) {
|
||||
case ElementType::BYTE:
|
||||
@@ -90,7 +93,7 @@ constexpr inline GLuint getComponentCount(ElementType type) noexcept {
|
||||
// Our enums to GLenum conversions
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
constexpr inline GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexcept {
|
||||
constexpr GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexcept {
|
||||
GLbitfield mask = 0;
|
||||
if (any(flags & TargetBufferFlags::COLOR_ALL)) {
|
||||
mask |= (GLbitfield)GL_COLOR_BUFFER_BIT;
|
||||
@@ -104,7 +107,7 @@ constexpr inline GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexc
|
||||
return mask;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBufferUsage(BufferUsage usage) noexcept {
|
||||
constexpr GLenum getBufferUsage(BufferUsage usage) noexcept {
|
||||
switch (usage) {
|
||||
case BufferUsage::STATIC:
|
||||
return GL_STATIC_DRAW;
|
||||
@@ -113,7 +116,7 @@ constexpr inline GLenum getBufferUsage(BufferUsage usage) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBufferBindingType(BufferObjectBinding bindingType) noexcept {
|
||||
constexpr GLenum getBufferBindingType(BufferObjectBinding bindingType) noexcept {
|
||||
switch (bindingType) {
|
||||
case BufferObjectBinding::VERTEX:
|
||||
return GL_ARRAY_BUFFER;
|
||||
@@ -134,11 +137,11 @@ constexpr inline GLenum getBufferBindingType(BufferObjectBinding bindingType) no
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLboolean getNormalization(bool normalized) noexcept {
|
||||
constexpr GLboolean getNormalization(bool normalized) noexcept {
|
||||
return GLboolean(normalized ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
||||
constexpr inline GLenum getComponentType(ElementType type) noexcept {
|
||||
constexpr GLenum getComponentType(ElementType type) noexcept {
|
||||
using ElementType = ElementType;
|
||||
switch (type) {
|
||||
case ElementType::BYTE:
|
||||
@@ -183,12 +186,30 @@ constexpr inline GLenum getComponentType(ElementType type) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getCubemapTarget(uint16_t layer) noexcept {
|
||||
constexpr GLenum getTextureTargetNotExternal(SamplerType target) noexcept {
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
return GL_TEXTURE_2D;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
return GL_TEXTURE_3D;
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
return GL_TEXTURE_2D_ARRAY;
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
return GL_TEXTURE_CUBE_MAP;
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
return GL_TEXTURE_CUBE_MAP_ARRAY;
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
// we should never be here
|
||||
return GL_TEXTURE_2D;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr GLenum getCubemapTarget(uint16_t layer) noexcept {
|
||||
assert_invariant(layer <= 5);
|
||||
return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
constexpr GLenum getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
using SamplerWrapMode = SamplerWrapMode;
|
||||
switch (mode) {
|
||||
case SamplerWrapMode::REPEAT:
|
||||
@@ -200,7 +221,7 @@ constexpr inline GLenum getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
|
||||
constexpr GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
|
||||
using SamplerMinFilter = SamplerMinFilter;
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
@@ -215,12 +236,12 @@ constexpr inline GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureFilter(SamplerMagFilter filter) noexcept {
|
||||
constexpr GLenum getTextureFilter(SamplerMagFilter filter) noexcept {
|
||||
return GL_NEAREST + GLenum(filter);
|
||||
}
|
||||
|
||||
|
||||
constexpr inline GLenum getBlendEquationMode(BlendEquation mode) noexcept {
|
||||
constexpr GLenum getBlendEquationMode(BlendEquation mode) noexcept {
|
||||
using BlendEquation = BlendEquation;
|
||||
switch (mode) {
|
||||
case BlendEquation::ADD: return GL_FUNC_ADD;
|
||||
@@ -231,7 +252,7 @@ constexpr inline GLenum getBlendEquationMode(BlendEquation mode) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
|
||||
constexpr GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
|
||||
using BlendFunction = BlendFunction;
|
||||
switch (mode) {
|
||||
case BlendFunction::ZERO: return GL_ZERO;
|
||||
@@ -248,7 +269,7 @@ constexpr inline GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
constexpr GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
switch (func) {
|
||||
case SamplerCompareFunc::LE: return GL_LEQUAL;
|
||||
case SamplerCompareFunc::GE: return GL_GEQUAL;
|
||||
@@ -262,25 +283,25 @@ constexpr inline GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
}
|
||||
|
||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
constexpr inline GLenum getTextureCompareMode(SamplerCompareMode mode) noexcept {
|
||||
constexpr GLenum getTextureCompareMode(SamplerCompareMode mode) noexcept {
|
||||
return mode == SamplerCompareMode::NONE ?
|
||||
GL_NONE : GL_COMPARE_REF_TO_TEXTURE;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
constexpr GLenum getTextureCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
return getCompareFunc(func);
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr inline GLenum getDepthFunc(SamplerCompareFunc func) noexcept {
|
||||
constexpr GLenum getDepthFunc(SamplerCompareFunc func) noexcept {
|
||||
return getCompareFunc(func);
|
||||
}
|
||||
|
||||
constexpr inline GLenum getStencilFunc(SamplerCompareFunc func) noexcept {
|
||||
constexpr GLenum getStencilFunc(SamplerCompareFunc func) noexcept {
|
||||
return getCompareFunc(func);
|
||||
}
|
||||
|
||||
constexpr inline GLenum getStencilOp(StencilOperation op) noexcept {
|
||||
constexpr GLenum getStencilOp(StencilOperation op) noexcept {
|
||||
switch (op) {
|
||||
case StencilOperation::KEEP: return GL_KEEP;
|
||||
case StencilOperation::ZERO: return GL_ZERO;
|
||||
@@ -293,7 +314,7 @@ constexpr inline GLenum getStencilOp(StencilOperation op) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getFormat(PixelDataFormat format) noexcept {
|
||||
constexpr GLenum getFormat(PixelDataFormat format) noexcept {
|
||||
using PixelDataFormat = PixelDataFormat;
|
||||
switch (format) {
|
||||
case PixelDataFormat::RGB: return GL_RGB;
|
||||
@@ -317,7 +338,7 @@ constexpr inline GLenum getFormat(PixelDataFormat format) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getType(PixelDataType type) noexcept {
|
||||
constexpr GLenum getType(PixelDataType type) noexcept {
|
||||
using PixelDataType = PixelDataType;
|
||||
switch (type) {
|
||||
case PixelDataType::UBYTE: return GL_UNSIGNED_BYTE;
|
||||
@@ -342,7 +363,7 @@ constexpr inline GLenum getType(PixelDataType type) noexcept {
|
||||
}
|
||||
|
||||
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
||||
constexpr inline GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
|
||||
constexpr GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
|
||||
using TextureSwizzle = TextureSwizzle;
|
||||
switch (c) {
|
||||
case TextureSwizzle::SUBSTITUTE_ZERO: return GL_ZERO;
|
||||
@@ -355,7 +376,7 @@ constexpr inline GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr inline GLenum getCullingMode(CullingMode mode) noexcept {
|
||||
constexpr GLenum getCullingMode(CullingMode mode) noexcept {
|
||||
switch (mode) {
|
||||
case CullingMode::NONE:
|
||||
// should never happen
|
||||
@@ -370,7 +391,7 @@ constexpr inline GLenum getCullingMode(CullingMode mode) noexcept {
|
||||
}
|
||||
|
||||
// ES2 supported internal formats for texturing and how they map to a format/type
|
||||
constexpr inline std::pair<GLenum, GLenum> textureFormatToFormatAndType(
|
||||
constexpr std::pair<GLenum, GLenum> textureFormatToFormatAndType(
|
||||
TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::R8: return { 0x1909 /*GL_LUMINANCE*/, GL_UNSIGNED_BYTE };
|
||||
|
||||
@@ -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
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -576,6 +582,10 @@ Handle<HwTexture> OpenGLDriver::createTextureViewSwizzleS() noexcept {
|
||||
return initHandle<GLTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> OpenGLDriver::createTextureExternalImage2S() noexcept {
|
||||
return initHandle<GLTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> OpenGLDriver::createTextureExternalImageS() noexcept {
|
||||
return initHandle<GLTexture>();
|
||||
}
|
||||
@@ -897,25 +907,7 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
||||
|
||||
t->gl.internalFormat = internalFormat;
|
||||
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
// we can't be here -- doesn't matter what we do
|
||||
case SamplerType::SAMPLER_2D:
|
||||
t->gl.target = GL_TEXTURE_2D;
|
||||
break;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
t->gl.target = GL_TEXTURE_3D;
|
||||
break;
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
t->gl.target = GL_TEXTURE_2D_ARRAY;
|
||||
break;
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
t->gl.target = GL_TEXTURE_CUBE_MAP;
|
||||
break;
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
t->gl.target = GL_TEXTURE_CUBE_MAP_ARRAY;
|
||||
break;
|
||||
}
|
||||
t->gl.target = getTextureTargetNotExternal(target);
|
||||
|
||||
if (t->samples > 1) {
|
||||
// Note: we can't be here in practice because filament's user API doesn't
|
||||
@@ -989,8 +981,7 @@ void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
|
||||
backend::TextureSwizzle a) {
|
||||
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
|
||||
|
||||
DEBUG_MARKER()
|
||||
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
|
||||
@@ -1052,6 +1043,57 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef image) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
usage |= TextureUsage::SAMPLEABLE;
|
||||
usage &= ~TextureUsage::UPLOADABLE;
|
||||
|
||||
auto& gl = mContext;
|
||||
GLenum internalFormat = getInternalFormat(format);
|
||||
if (UTILS_UNLIKELY(gl.isES2())) {
|
||||
// on ES2, format and internal format must match
|
||||
// FIXME: handle compressed texture format
|
||||
internalFormat = textureFormatToFormatAndType(format).first;
|
||||
}
|
||||
assert_invariant(internalFormat);
|
||||
|
||||
GLTexture* const t = construct<GLTexture>(th, target, 1, 1, width, height, 1, format, usage);
|
||||
assert_invariant(t);
|
||||
|
||||
t->externalTexture = mPlatform.createExternalImageTexture();
|
||||
if (t->externalTexture) {
|
||||
if (target == SamplerType::SAMPLER_EXTERNAL) {
|
||||
if (UTILS_LIKELY(gl.ext.OES_EGL_image_external_essl3)) {
|
||||
t->externalTexture->target = GL_TEXTURE_EXTERNAL_OES;
|
||||
} else {
|
||||
// revert to texture 2D if external is not supported; what else can we do?
|
||||
t->externalTexture->target = GL_TEXTURE_2D;
|
||||
}
|
||||
} else {
|
||||
t->externalTexture->target = getTextureTargetNotExternal(target);
|
||||
}
|
||||
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
// internalFormat actually depends on the external image, but it doesn't matter
|
||||
// because it's not used anywhere for anything important.
|
||||
t->gl.internalFormat = internalFormat;
|
||||
t->gl.baseLevel = 0;
|
||||
t->gl.maxLevel = 0;
|
||||
t->gl.external = true; // forces bindTexture() call (they're never cached)
|
||||
}
|
||||
|
||||
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
|
||||
if (mPlatform.setExternalImage(image, t->externalTexture)) {
|
||||
// the target and id can be reset each time
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image) {
|
||||
DEBUG_MARKER()
|
||||
@@ -1073,6 +1115,16 @@ void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType
|
||||
|
||||
t->externalTexture = mPlatform.createExternalImageTexture();
|
||||
if (t->externalTexture) {
|
||||
if (target == SamplerType::SAMPLER_EXTERNAL) {
|
||||
if (UTILS_LIKELY(gl.ext.OES_EGL_image_external_essl3)) {
|
||||
t->externalTexture->target = GL_TEXTURE_EXTERNAL_OES;
|
||||
} else {
|
||||
// revert to texture 2D if external is not supported; what else can we do?
|
||||
t->externalTexture->target = GL_TEXTURE_2D;
|
||||
}
|
||||
} else {
|
||||
t->externalTexture->target = getTextureTargetNotExternal(target);
|
||||
}
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
// internalFormat actually depends on the external image, but it doesn't matter
|
||||
@@ -1864,7 +1916,7 @@ void OpenGLDriver::destroyTexture(Handle<HwTexture> th) {
|
||||
detachStream(t);
|
||||
}
|
||||
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
|
||||
mPlatform.destroyExternalImage(t->externalTexture);
|
||||
mPlatform.destroyExternalImageTexture(t->externalTexture);
|
||||
} else {
|
||||
glDeleteTextures(1, &t->gl.id);
|
||||
}
|
||||
@@ -2803,6 +2855,10 @@ void OpenGLDriver::setCompressedTextureData(GLTexture* t, uint32_t level,
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
mPlatform.retainExternalImage(image);
|
||||
}
|
||||
|
||||
void OpenGLDriver::setupExternalImage(void* image) {
|
||||
mPlatform.retainExternalImage(image);
|
||||
}
|
||||
@@ -3433,6 +3489,14 @@ void OpenGLDriver::whenFrameComplete(const std::function<void()>& fn) noexcept {
|
||||
|
||||
void OpenGLDriver::whenGpuCommandsComplete(const std::function<void()>& fn) noexcept {
|
||||
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
// glFenceSync can return 0 in certain situations. For example, we've seen this happen on Web
|
||||
// when the GL context has been lost.
|
||||
// Unfortunately, there's not much we can do here. The fn callback will never execute, which
|
||||
// could cause issues. If we've lost the WebGL context though, Filament is most likely shutting
|
||||
// down anyway, so in practice this might not be a big problem.
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
mGpuCommandCompleteOps.emplace_back(sync, fn);
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
@@ -4090,4 +4154,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
|
||||
|
||||
@@ -121,14 +121,24 @@ OpenGLPlatform::ExternalTexture* OpenGLPlatform::createExternalImageTexture() no
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OpenGLPlatform::destroyExternalImage(
|
||||
void OpenGLPlatform::destroyExternalImageTexture(
|
||||
UTILS_UNUSED ExternalTexture* texture) noexcept {
|
||||
}
|
||||
|
||||
void OpenGLPlatform::retainExternalImage(
|
||||
UTILS_UNUSED ExternalImageHandleRef externalImage) noexcept {
|
||||
}
|
||||
|
||||
void OpenGLPlatform::retainExternalImage(
|
||||
UTILS_UNUSED void* externalImage) noexcept {
|
||||
}
|
||||
|
||||
bool OpenGLPlatform::setExternalImage(
|
||||
UTILS_UNUSED ExternalImageHandleRef externalImage,
|
||||
UTILS_UNUSED ExternalTexture* texture) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OpenGLPlatform::setExternalImage(
|
||||
UTILS_UNUSED void* externalImage,
|
||||
UTILS_UNUSED ExternalTexture* texture) noexcept {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -54,8 +54,15 @@ struct PlatformCocoaGLImpl {
|
||||
CVOpenGLTextureCacheRef mTextureCache = nullptr;
|
||||
std::unique_ptr<CocoaExternalImage::SharedGl> mExternalImageSharedGl;
|
||||
void updateOpenGLContext(NSView *nsView, bool resetView, bool clearView);
|
||||
struct ExternalImageCocoaGL : public Platform::ExternalImage {
|
||||
CVPixelBufferRef cvBuffer;
|
||||
protected:
|
||||
~ExternalImageCocoaGL() noexcept final;
|
||||
};
|
||||
};
|
||||
|
||||
PlatformCocoaGLImpl::ExternalImageCocoaGL::~ExternalImageCocoaGL() noexcept = default;
|
||||
|
||||
CocoaGLSwapChain::CocoaGLSwapChain( NSView* inView )
|
||||
: view(inView)
|
||||
, previousBounds(NSZeroRect)
|
||||
@@ -309,17 +316,12 @@ OpenGLPlatform::ExternalTexture* PlatformCocoaGL::createExternalImageTexture() n
|
||||
if (!pImpl->mExternalImageSharedGl) {
|
||||
pImpl->mExternalImageSharedGl = std::make_unique<CocoaExternalImage::SharedGl>();
|
||||
}
|
||||
|
||||
ExternalTexture* outTexture = new CocoaExternalImage(pImpl->mTextureCache,
|
||||
*pImpl->mExternalImageSharedGl);
|
||||
|
||||
// the actual id/target will be set in setExternalImage.
|
||||
outTexture->id = 0;
|
||||
outTexture->target = GL_TEXTURE_2D;
|
||||
return outTexture;
|
||||
}
|
||||
|
||||
void PlatformCocoaGL::destroyExternalImage(ExternalTexture* texture) noexcept {
|
||||
void PlatformCocoaGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
|
||||
auto* p = static_cast<CocoaExternalImage*>(texture);
|
||||
delete p;
|
||||
}
|
||||
@@ -344,6 +346,36 @@ bool PlatformCocoaGL::setExternalImage(void* externalImage, ExternalTexture* tex
|
||||
return true;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle PlatformCocoaGL::createExternalImage(void* cvPixelBuffer) noexcept {
|
||||
auto* p = new(std::nothrow) PlatformCocoaGLImpl::ExternalImageCocoaGL;
|
||||
p->cvBuffer = (CVPixelBufferRef) cvPixelBuffer;
|
||||
return ExternalImageHandle{ p };
|
||||
}
|
||||
|
||||
void PlatformCocoaGL::retainExternalImage(ExternalImageHandleRef externalImage) noexcept {
|
||||
auto const* const cocoaGlExternalImage
|
||||
= static_cast<PlatformCocoaGLImpl::ExternalImageCocoaGL const*>(externalImage.get());
|
||||
// Take ownership of the passed in buffer. It will be released the next time
|
||||
// setExternalImage is called, or when the texture is destroyed.
|
||||
CVPixelBufferRef pixelBuffer = cocoaGlExternalImage->cvBuffer;
|
||||
CVPixelBufferRetain(pixelBuffer);
|
||||
}
|
||||
|
||||
bool PlatformCocoaGL::setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept {
|
||||
auto const* const cocoaGlExternalImage
|
||||
= static_cast<PlatformCocoaGLImpl::ExternalImageCocoaGL const*>(externalImage.get());
|
||||
CVPixelBufferRef cvPixelBuffer = cocoaGlExternalImage->cvBuffer;
|
||||
CocoaExternalImage* cocoaExternalImage = static_cast<CocoaExternalImage*>(texture);
|
||||
if (!cocoaExternalImage->set(cvPixelBuffer)) {
|
||||
return false;
|
||||
}
|
||||
texture->target = cocoaExternalImage->getTarget();
|
||||
texture->id = cocoaExternalImage->getGlTexture();
|
||||
// we used to set the internalFormat, but it's not used anywhere on the gl backend side
|
||||
// cocoaExternalImage->getInternalFormat();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlatformCocoaGLImpl::updateOpenGLContext(NSView *nsView, bool resetView,
|
||||
bool clearView) {
|
||||
NSOpenGLContext* glContext = mGLContext;
|
||||
|
||||
@@ -47,8 +47,15 @@ struct PlatformCocoaTouchGLImpl {
|
||||
GLuint mDefaultDepthbuffer = 0;
|
||||
CVOpenGLESTextureCacheRef mTextureCache = nullptr;
|
||||
CocoaTouchExternalImage::SharedGl* mExternalImageSharedGl = nullptr;
|
||||
struct ExternalImageCocoaTouchGL : public Platform::ExternalImage {
|
||||
CVPixelBufferRef cvBuffer;
|
||||
protected:
|
||||
~ExternalImageCocoaTouchGL() noexcept final;
|
||||
};
|
||||
};
|
||||
|
||||
PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL::~ExternalImageCocoaTouchGL() noexcept = default;
|
||||
|
||||
PlatformCocoaTouchGL::PlatformCocoaTouchGL()
|
||||
: pImpl(new PlatformCocoaTouchGLImpl) {
|
||||
}
|
||||
@@ -198,13 +205,10 @@ void PlatformCocoaTouchGL::commit(Platform::SwapChain* swapChain) noexcept {
|
||||
OpenGLPlatform::ExternalTexture* PlatformCocoaTouchGL::createExternalImageTexture() noexcept {
|
||||
ExternalTexture* outTexture = new CocoaTouchExternalImage(pImpl->mTextureCache,
|
||||
*pImpl->mExternalImageSharedGl);
|
||||
// the actual id/target will be set in setExternalImage*(
|
||||
outTexture->id = 0;
|
||||
outTexture->target = GL_TEXTURE_2D;
|
||||
return outTexture;
|
||||
}
|
||||
|
||||
void PlatformCocoaTouchGL::destroyExternalImage(ExternalTexture* texture) noexcept {
|
||||
void PlatformCocoaTouchGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
|
||||
auto* p = static_cast<CocoaTouchExternalImage*>(texture);
|
||||
delete p;
|
||||
}
|
||||
@@ -229,4 +233,35 @@ bool PlatformCocoaTouchGL::setExternalImage(void* externalImage, ExternalTexture
|
||||
return true;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle PlatformCocoaTouchGL::createExternalImage(void* cvPixelBuffer) noexcept {
|
||||
auto* p = new(std::nothrow) PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL;
|
||||
p->cvBuffer = (CVPixelBufferRef) cvPixelBuffer;
|
||||
return ExternalImageHandle{ p };
|
||||
}
|
||||
|
||||
void PlatformCocoaTouchGL::retainExternalImage(ExternalImageHandleRef externalImage) noexcept {
|
||||
auto const* const cocoaTouchGlExternalImage
|
||||
= static_cast<PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL const*>(externalImage.get());
|
||||
// Take ownership of the passed in buffer. It will be released the next time
|
||||
// setExternalImage is called, or when the texture is destroyed.
|
||||
CVPixelBufferRef pixelBuffer = cocoaTouchGlExternalImage->cvBuffer;
|
||||
CVPixelBufferRetain(pixelBuffer);
|
||||
}
|
||||
|
||||
bool PlatformCocoaTouchGL::setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept {
|
||||
auto const* const cocoaTouchGlExternalImage
|
||||
= static_cast<PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL const*>(externalImage.get());
|
||||
CVPixelBufferRef cvPixelBuffer = cocoaTouchGlExternalImage->cvBuffer;
|
||||
CocoaTouchExternalImage* cocoaExternalImage = static_cast<CocoaTouchExternalImage*>(texture);
|
||||
if (!cocoaExternalImage->set(cvPixelBuffer)) {
|
||||
return false;
|
||||
}
|
||||
texture->target = cocoaExternalImage->getTarget();
|
||||
texture->id = cocoaExternalImage->getGlTexture();
|
||||
// we used to set the internalFormat, but it's not used anywhere on the gl backend side
|
||||
// cocoaExternalImage->getInternalFormat();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -117,7 +117,9 @@ bool PlatformEGL::isOpenGL() const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
PlatformEGL::ExternalImageEGL::~ExternalImageEGL() = default;
|
||||
|
||||
Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& driverConfig) noexcept {
|
||||
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
assert_invariant(mEGLDisplay != EGL_NO_DISPLAY);
|
||||
|
||||
@@ -699,16 +701,10 @@ FenceStatus PlatformEGL::waitFence(
|
||||
OpenGLPlatform::ExternalTexture* PlatformEGL::createExternalImageTexture() noexcept {
|
||||
ExternalTexture* outTexture = new(std::nothrow) ExternalTexture{};
|
||||
glGenTextures(1, &outTexture->id);
|
||||
if (UTILS_LIKELY(ext.gl.OES_EGL_image_external_essl3)) {
|
||||
outTexture->target = GL_TEXTURE_EXTERNAL_OES;
|
||||
} else {
|
||||
// if texture external is not supported, revert to texture 2d
|
||||
outTexture->target = GL_TEXTURE_2D;
|
||||
}
|
||||
return outTexture;
|
||||
}
|
||||
|
||||
void PlatformEGL::destroyExternalImage(ExternalTexture* texture) noexcept {
|
||||
void PlatformEGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
|
||||
glDeleteTextures(1, &texture->id);
|
||||
delete texture;
|
||||
}
|
||||
@@ -728,6 +724,18 @@ bool PlatformEGL::setExternalImage(void* externalImage,
|
||||
return true;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle PlatformEGL::createExternalImage(EGLImageKHR eglImage) noexcept {
|
||||
auto* const p = new(std::nothrow) ExternalImageEGL;
|
||||
p->eglImage = eglImage;
|
||||
return ExternalImageHandle{p};
|
||||
}
|
||||
|
||||
bool PlatformEGL::setExternalImage(ExternalImageHandleRef externalImage,
|
||||
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
|
||||
auto const* const eglExternalImage = static_cast<ExternalImageEGL const*>(externalImage.get());
|
||||
return setExternalImage(eglExternalImage->eglImage, texture);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
void PlatformEGL::initializeGlExtensions() noexcept {
|
||||
|
||||
@@ -231,6 +231,26 @@ Driver* PlatformEGLAndroid::createDriver(void* sharedContext,
|
||||
return driver;
|
||||
}
|
||||
|
||||
PlatformEGLAndroid::ExternalImageEGLAndroid::~ExternalImageEGLAndroid() = default;
|
||||
|
||||
Platform::ExternalImageHandle PlatformEGLAndroid::createExternalImage(AHardwareBuffer const* buffer, bool sRGB) noexcept {
|
||||
auto* const p = new(std::nothrow) ExternalImageEGLAndroid;
|
||||
p->aHardwareBuffer = const_cast<AHardwareBuffer*>(buffer);
|
||||
p->sRGB = sRGB;
|
||||
return ExternalImageHandle{ p };
|
||||
}
|
||||
|
||||
bool PlatformEGLAndroid::setExternalImage(ExternalImageHandleRef externalImage,
|
||||
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
|
||||
auto const* const eglExternalImage = static_cast<ExternalImageEGLAndroid const*>(externalImage.get());
|
||||
if (eglExternalImage->aHardwareBuffer) {
|
||||
// TODO: implement PlatformEGLAndroid::setExternalImage w/ AHardwareBuffer
|
||||
return true;
|
||||
}
|
||||
// not a AHardwareBuffer, fallback to the inherited version
|
||||
return PlatformEGL::setExternalImage(externalImage, texture);
|
||||
}
|
||||
|
||||
void PlatformEGLAndroid::setPresentationTime(int64_t presentationTimeInNanosecond) noexcept {
|
||||
EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
|
||||
if (currentDrawSurface != EGL_NO_SURFACE) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -175,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,25 @@ 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,
|
||||
void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th,
|
||||
backend::SamplerType target, backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage, void* externalImage) {
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef externalImage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
// FIXME: implement createTextureExternalImage2R
|
||||
}
|
||||
|
||||
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 +573,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);
|
||||
|
||||
@@ -783,6 +801,10 @@ Handle<HwTexture> VulkanDriver::createTextureViewSwizzleS() noexcept {
|
||||
return mResourceManager.allocHandle<VulkanTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> VulkanDriver::createTextureExternalImage2S() noexcept {
|
||||
return mResourceManager.allocHandle<VulkanTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> VulkanDriver::createTextureExternalImageS() noexcept {
|
||||
return mResourceManager.allocHandle<VulkanTexture>();
|
||||
}
|
||||
@@ -930,7 +952,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 +979,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 +1037,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 +1112,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 };
|
||||
}
|
||||
|
||||
@@ -1163,6 +1184,9 @@ void VulkanDriver::update3DImage(Handle<HwTexture> th, uint32_t level, uint32_t
|
||||
scheduleDestroy(std::move(data));
|
||||
}
|
||||
|
||||
void VulkanDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
}
|
||||
|
||||
void VulkanDriver::setupExternalImage(void* image) {
|
||||
}
|
||||
|
||||
@@ -1673,25 +1697,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 +1752,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 +1901,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{
|
||||
@@ -281,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;
|
||||
@@ -401,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.");
|
||||
@@ -461,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();
|
||||
@@ -508,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);
|
||||
}
|
||||
@@ -557,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,
|
||||
@@ -600,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,
|
||||
@@ -615,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,
|
||||
@@ -650,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,
|
||||
@@ -673,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>
|
||||
@@ -126,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. "
|
||||
@@ -172,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 };
|
||||
@@ -212,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 };
|
||||
@@ -473,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;
|
||||
@@ -508,7 +508,7 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
|
||||
|
||||
// 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) {
|
||||
@@ -560,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.
|
||||
@@ -579,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) {
|
||||
@@ -597,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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
@@ -70,7 +71,7 @@ class UTILS_PUBLIC Texture : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
static constexpr const size_t BASE_LEVEL = 0;
|
||||
static constexpr size_t BASE_LEVEL = 0;
|
||||
|
||||
//! Face offsets for all faces of a cubemap
|
||||
struct FaceOffsets;
|
||||
@@ -84,14 +85,16 @@ public:
|
||||
using CompressedType = backend::CompressedPixelDataType; //!< Compressed pixel data format
|
||||
using Usage = backend::TextureUsage; //!< Usage affects texel layout
|
||||
using Swizzle = backend::TextureSwizzle; //!< Texture swizzle
|
||||
using ExternalImageHandle = backend::Platform::ExternalImageHandle;
|
||||
using ExternalImageHandleRef = backend::Platform::ExternalImageHandleRef;
|
||||
|
||||
/** @return whether a backend supports a particular format. */
|
||||
/** @return Whether a backend supports a particular format. */
|
||||
static bool isTextureFormatSupported(Engine& engine, InternalFormat format) noexcept;
|
||||
|
||||
/** @return whether this backend supports protected textures. */
|
||||
/** @return Whether this backend supports protected textures. */
|
||||
static bool isProtectedTexturesSupported(Engine& engine) noexcept;
|
||||
|
||||
/** @return whether a backend supports texture swizzling. */
|
||||
/** @return Whether a backend supports texture swizzling. */
|
||||
static bool isTextureSwizzleSupported(Engine& engine) noexcept;
|
||||
|
||||
static size_t computeTextureDataSize(Format format, Type type,
|
||||
@@ -217,6 +220,18 @@ public:
|
||||
*/
|
||||
Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept;
|
||||
|
||||
/**
|
||||
* Creates an external texture. The content must be set using setExternalImage().
|
||||
* The sampler can be SAMPLER_EXTERNAL or SAMPLER_2D depending on the format. Generally
|
||||
* YUV formats must use SAMPLER_EXTERNAL. This depends on the backend features and is not
|
||||
* validated.
|
||||
*
|
||||
* If the Sampler is set to SAMPLER_EXTERNAL, external() is implied.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Builder& external() noexcept;
|
||||
|
||||
/**
|
||||
* Creates the Texture object and returns a pointer to it.
|
||||
*
|
||||
@@ -261,18 +276,6 @@ public:
|
||||
*/
|
||||
Builder& import(intptr_t id) noexcept;
|
||||
|
||||
/**
|
||||
* Creates an external texture. The content must be set using setExternalImage().
|
||||
* The sampler can be SAMPLER_EXTERNAL or SAMPLER_2D depending on the format. Generally
|
||||
* YUV formats must use SAMPLER_EXTERNAL. This depends on the backend features and is not
|
||||
* validated.
|
||||
*
|
||||
* If the Sampler is set to SAMPLER_EXTERNAL, external() is implied.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Builder& external() noexcept;
|
||||
|
||||
private:
|
||||
friend class FTexture;
|
||||
};
|
||||
@@ -359,7 +362,7 @@ public:
|
||||
* uint32_t width, uint32_t height, uint32_t depth,
|
||||
* PixelBufferDescriptor&& buffer)
|
||||
*/
|
||||
inline void setImage(Engine& engine, size_t level, PixelBufferDescriptor&& buffer) const {
|
||||
void setImage(Engine& engine, size_t level, PixelBufferDescriptor&& buffer) const {
|
||||
setImage(engine, level, 0, 0, 0,
|
||||
uint32_t(getWidth(level)), uint32_t(getHeight(level)), 1, std::move(buffer));
|
||||
}
|
||||
@@ -372,7 +375,7 @@ public:
|
||||
* uint32_t width, uint32_t height, uint32_t depth,
|
||||
* PixelBufferDescriptor&& buffer)
|
||||
*/
|
||||
inline void setImage(Engine& engine, size_t level,
|
||||
void setImage(Engine& engine, size_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
|
||||
PixelBufferDescriptor&& buffer) const {
|
||||
setImage(engine, level, xoffset, yoffset, 0, width, height, 1, std::move(buffer));
|
||||
@@ -406,6 +409,26 @@ public:
|
||||
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the external image to associate with this Texture. Typically, the external
|
||||
* image is OS specific, and can be a video or camera frame.
|
||||
* There are many restrictions when using an external image as a texture, such as:
|
||||
* - only the level of detail (lod) 0 can be specified
|
||||
* - only nearest or linear filtering is supported
|
||||
* - the size and format of the texture is defined by the external image
|
||||
* - only the CLAMP_TO_EDGE wrap mode is supported
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param image An opaque handle to a platform specific image. It must be created using Platform
|
||||
* specific APIs. For example PlatformEGL::createExternalImage(EGLImageKHR eglImage)
|
||||
*
|
||||
* @see PlatformEGL::createExternalImage
|
||||
* @see PlatformEGLAndroid::createExternalImage
|
||||
* @see PlatformCocoaGL::createExternalImage
|
||||
* @see PlatformCocoaTouchGL::createExternalImage
|
||||
*/
|
||||
void setExternalImage(Engine& engine, ExternalImageHandleRef image) noexcept;
|
||||
|
||||
/**
|
||||
* Specify the external image to associate with this Texture. Typically, the external
|
||||
* image is OS specific, and can be a video or camera frame.
|
||||
@@ -428,7 +451,9 @@ public:
|
||||
*
|
||||
* @see Builder::sampler()
|
||||
*
|
||||
* @deprecated Instead, use setExternalImage(Engine& engine, ExternalImageHandleRef image)
|
||||
*/
|
||||
UTILS_DEPRECATED
|
||||
void setExternalImage(Engine& engine, void* UTILS_NONNULL image) noexcept;
|
||||
|
||||
/**
|
||||
@@ -463,7 +488,7 @@ public:
|
||||
void setExternalImage(Engine& engine, void* UTILS_NONNULL image, size_t plane) noexcept;
|
||||
|
||||
/**
|
||||
* Specify the external stream to associate with this Texture. Typically the external
|
||||
* Specify the external stream to associate with this Texture. Typically, the external
|
||||
* stream is OS specific, and can be a video or camera stream.
|
||||
* There are many restrictions when using an external stream as a texture, such as:
|
||||
* - only the level of detail (lod) 0 can be specified
|
||||
@@ -474,7 +499,7 @@ public:
|
||||
* @param stream A Stream object
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_EXTERNAL or it has no effect
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_EXTERNAL, or it has no effect
|
||||
*
|
||||
* @see Builder::sampler(), Stream
|
||||
*
|
||||
@@ -522,9 +547,9 @@ public:
|
||||
* @param buffer Client-side buffer containing the images to set.
|
||||
* @param faceOffsets Offsets in bytes into \p buffer for all six images. The offsets
|
||||
* are specified in the following order: +x, -x, +y, -y, +z, -z
|
||||
* @param options Optional parameter to controlling user-specified quality and options.
|
||||
* @param options Optional parameter controlling user-specified quality and options.
|
||||
*
|
||||
* @exception utils::PreConditionPanic if the source data constraints are not respected.
|
||||
* @exception utils::PreConditionPanic If the source data constraints are not respected.
|
||||
*
|
||||
*/
|
||||
void generatePrefilterMipmap(Engine& engine,
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -58,6 +58,10 @@ void Texture::setImage(Engine& engine, size_t const level,
|
||||
downcast(this)->setImage(downcast(engine), level, std::move(buffer), faceOffsets);
|
||||
}
|
||||
|
||||
void Texture::setExternalImage(Engine& engine, ExternalImageHandleRef image) noexcept {
|
||||
downcast(this)->setExternalImage(downcast(engine), image);
|
||||
}
|
||||
|
||||
void Texture::setExternalImage(Engine& engine, void* image) noexcept {
|
||||
downcast(this)->setExternalImage(downcast(engine), image);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1103,8 +1103,13 @@ void FMaterial::precacheDepthVariants(FEngine const& engine) {
|
||||
// later, when/if needed by createAndCacheProgram(). Doing it now potentially uses more
|
||||
// memory and increases init time, but reduces hiccups during the first frame.
|
||||
if (UTILS_UNLIKELY(mIsDefaultMaterial)) {
|
||||
const bool stereoSupported = mEngine.getDriverApi().isStereoSupported();
|
||||
auto const allDepthVariants = VariantUtils::getDepthVariants();
|
||||
for (auto const variant: allDepthVariants) {
|
||||
// Don't precache any stereo variants if stereo is not supported.
|
||||
if (!stereoSupported && Variant::isStereoVariant(variant)) {
|
||||
continue;
|
||||
}
|
||||
assert_invariant(Variant::isValidDepthVariant(variant));
|
||||
if (hasVariant(variant)) {
|
||||
prepareProgram(variant);
|
||||
|
||||
@@ -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
|
||||
@@ -1443,6 +1443,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 {
|
||||
|
||||
@@ -469,6 +469,26 @@ void FTexture::setImage(FEngine& engine, size_t const level,
|
||||
const_cast<FTexture*>(this)->updateLodRange(level);
|
||||
}
|
||||
|
||||
void FTexture::setExternalImage(FEngine& engine, ExternalImageHandleRef image) noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
|
||||
|
||||
// The call to setupExternalImage2 is synchronous, and allows the driver to take ownership of the
|
||||
// external image on this thread, if necessary.
|
||||
auto& api = engine.getDriverApi();
|
||||
api.setupExternalImage2(image);
|
||||
|
||||
auto texture = api.createTextureExternalImage2(mTarget, mFormat, mWidth, mHeight, mUsage, image);
|
||||
|
||||
if (mTextureIsSwizzled) {
|
||||
auto const& s = mSwizzle;
|
||||
auto swizzleView = api.createTextureViewSwizzle(texture, s[0], s[1], s[2], s[3]);
|
||||
api.destroyTexture(texture);
|
||||
texture = swizzleView;
|
||||
}
|
||||
|
||||
setHandles(texture);
|
||||
}
|
||||
|
||||
void FTexture::setExternalImage(FEngine& engine, void* image) noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ public:
|
||||
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
|
||||
PrefilterOptions const* options);
|
||||
|
||||
void setExternalImage(FEngine& engine, ExternalImageHandleRef image) noexcept;
|
||||
void setExternalImage(FEngine& engine, void* image) noexcept;
|
||||
void setExternalImage(FEngine& engine, void* image, size_t plane) noexcept;
|
||||
void setExternalStream(FEngine& engine, FStream* stream) 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);
|
||||
|
||||
@@ -409,21 +419,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 +441,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 +485,7 @@ io::sstream& CodeGenerator::generateVariable(io::sstream& out, ShaderStage stage
|
||||
return out;
|
||||
}
|
||||
|
||||
io::sstream& CodeGenerator::generateShaderInputs(io::sstream& out, ShaderStage type,
|
||||
io::sstream& CodeGenerator::generateSurfaceShaderInputs(io::sstream& out, ShaderStage stage,
|
||||
const AttributeBitset& attributes, Interpolation interpolation,
|
||||
MaterialBuilder::PushConstantList const& pushConstants) const {
|
||||
auto const& attributeDatabase = MaterialBuilder::getAttributeDatabase();
|
||||
@@ -488,7 +498,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 +517,16 @@ io::sstream& CodeGenerator::generateShaderInputs(io::sstream& out, ShaderStage t
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
out << SHADERS_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 +587,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 +786,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 +835,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 +1023,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 +1045,87 @@ 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) {
|
||||
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 +1133,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& generateSurfaceShaderInputs(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,
|
||||
|
||||
@@ -370,7 +370,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 +389,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 +436,15 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
|
||||
[](MaterialBuilder::PushConstant const& constant) {
|
||||
return constant.stage == ShaderStage::VERTEX;
|
||||
});
|
||||
cg.generateShaderInputs(vs, ShaderStage::VERTEX, attributes, interpolation,
|
||||
cg.generateSurfaceShaderInputs(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 +478,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 +489,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 +522,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 +546,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.generateSurfaceShaderInputs(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 +626,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 +656,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 +688,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 +704,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 +728,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 +737,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 +753,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 +762,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
|
||||
|
||||
CodeGenerator::generatePostProcessMain(vs, ShaderStage::VERTEX);
|
||||
|
||||
CodeGenerator::generateEpilog(vs);
|
||||
CodeGenerator::generateCommonEpilog(vs);
|
||||
return vs.c_str();
|
||||
}
|
||||
|
||||
@@ -773,7 +772,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 +781,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 +794,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 +818,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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user