Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
815629f14e | ||
|
|
c05a446e10 | ||
|
|
9d49205844 | ||
|
|
7099b6dd6f | ||
|
|
18becfc656 | ||
|
|
cd2d499e25 | ||
|
|
3bb72cefe9 | ||
|
|
1a67f9233b | ||
|
|
f7e20562a8 | ||
|
|
08af16239c |
@@ -7,3 +7,5 @@ for next branch cut* header.
|
||||
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
|
||||
- materials: sampler now export their type in the material binary [⚠️ **New Material Version**]
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.60.1'
|
||||
implementation 'com.google.android.filament:filament-android:1.59.5'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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.60.1'
|
||||
pod 'Filament', '~> 1.59.5'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
+1
-6
@@ -7,15 +7,10 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.60.1
|
||||
|
||||
|
||||
## v1.60.0
|
||||
|
||||
- materials: remove dependence on per-view descset layout from filamat. [⚠️ **New Material Version**]
|
||||
- matc non-functional change: Update GLSL postprocessor to
|
||||
isolate calls to SPVRemap from calls to SPIRV-Cross.
|
||||
|
||||
- `ColorGrading::Builder::toneMapper` now takes a `shared_ptr<ToneMapper>`
|
||||
|
||||
## v1.59.5
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <filament/ColorGrading.h>
|
||||
#include <filament/ToneMapper.h>
|
||||
#include <memory>
|
||||
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
@@ -67,8 +68,9 @@ extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_ColorGrading_nBuilderToneMapper(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jlong toneMapper_) {
|
||||
ColorGrading::Builder* builder = (ColorGrading::Builder*) nativeBuilder;
|
||||
const ToneMapper* toneMapper = (const ToneMapper*) toneMapper_;
|
||||
builder->toneMapper(toneMapper);
|
||||
ToneMapper* toneMapper = reinterpret_cast<ToneMapper*>(toneMapper_);
|
||||
std::shared_ptr<ToneMapper> toneMapperCopy(toneMapper->clone());
|
||||
builder->toneMapper(toneMapperCopy);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
|
||||
+3
-3
@@ -214,9 +214,9 @@ public class ColorGrading {
|
||||
*
|
||||
* The default tone mapping operator is {@link ToneMapper.ACESLegacy}.
|
||||
*
|
||||
* The specified tone mapper must have a lifecycle that exceeds the lifetime of
|
||||
* this builder. Since the build(Engine&) method is synchronous, it is safe to
|
||||
* delete the tone mapper object after that finishes executing.
|
||||
* The copy of the specified tone mapper is set to this builder. It is safe to delete
|
||||
* the original tone mapper object while the copied one is held by the built ColorGrading
|
||||
* object.
|
||||
*
|
||||
* @param toneMapper The tone mapping operator to apply to the HDR color buffer
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.60.1
|
||||
VERSION_NAME=1.59.5
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ function print_fgviewer_help {
|
||||
}
|
||||
|
||||
# Unless explicitly specified, NDK version will be selected as highest available version within same major release chain
|
||||
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/build/common/versions | grep GITHUB_NDK_VERSION | sed s/GITHUB_NDK_VERSION=//g | cut -f 1 -d ".")}
|
||||
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/build/common/versions | grep GITHUB_NDK_VERSION | cut -f 1 -d ".")}
|
||||
|
||||
# Requirements
|
||||
CMAKE_MAJOR=3
|
||||
@@ -463,6 +463,16 @@ function ensure_android_build {
|
||||
echo "Error: Android NDK side-by-side version ${FILAMENT_NDK_VERSION} or compatible must be installed, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local cmake_version=$(cmake --version)
|
||||
if [[ "${cmake_version}" =~ ([0-9]+)\.([0-9]+)\.[0-9]+ ]]; then
|
||||
if [[ "${BASH_REMATCH[1]}" -lt "${CMAKE_MAJOR}" ]] || \
|
||||
[[ "${BASH_REMATCH[2]}" -lt "${CMAKE_MINOR}" ]]; then
|
||||
echo "Error: cmake version ${CMAKE_MAJOR}.${CMAKE_MINOR}+ is required," \
|
||||
"${BASH_REMATCH[1]}.${BASH_REMATCH[2]} installed, exiting"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function build_android {
|
||||
|
||||
@@ -1023,12 +1023,8 @@ samplerCubemap | Cubemap texture
|
||||
[Table [materialParamsTypes]: Material parameter types]
|
||||
|
||||
Samplers
|
||||
: Sampler types can specify additional options:
|
||||
|
||||
- `format`: either `int` or `float` (defaults to `float`).
|
||||
- `stages`: array of strings containing the list of shader stages this
|
||||
sampler can be accessed from. Each entry must be either `vertex` or
|
||||
`fragment` (defaults to both).
|
||||
: Sampler types can also specify a `format` which can be either `int` or `float` (defaults to
|
||||
`float`).
|
||||
|
||||
Arrays
|
||||
: A parameter can define an array of values by appending `[size]` after the type name, where
|
||||
|
||||
@@ -20,15 +20,10 @@
|
||||
#define TNT_FILAMENT_BACKEND_BUFFERDESCRIPTOR_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <utility>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace utils::io {
|
||||
class ostream;
|
||||
} // namespace utils::io
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class CallbackHandler;
|
||||
@@ -94,8 +89,8 @@ public:
|
||||
* @param callback A callback used to release the CPU buffer from this BufferDescriptor
|
||||
* @param user An opaque user pointer passed to the callback function when it's called
|
||||
*/
|
||||
BufferDescriptor(void const* buffer, size_t const size,
|
||||
Callback const callback = nullptr, void* user = nullptr) noexcept
|
||||
BufferDescriptor(void const* buffer, size_t size,
|
||||
Callback callback = nullptr, void* user = nullptr) noexcept
|
||||
: buffer(const_cast<void*>(buffer)), size(size), mCallback(callback), mUser(user) {
|
||||
}
|
||||
|
||||
@@ -103,12 +98,11 @@ public:
|
||||
* Creates a BufferDescriptor that references a CPU memory-buffer
|
||||
* @param buffer Memory address of the CPU buffer to reference
|
||||
* @param size Size of the CPU buffer in bytes
|
||||
* @param handler A custom handler for the callback
|
||||
* @param callback A callback used to release the CPU buffer from this BufferDescriptor
|
||||
* @param user An opaque user pointer passed to the callback function when it's called
|
||||
*/
|
||||
BufferDescriptor(void const* buffer, size_t const size,
|
||||
CallbackHandler* handler, Callback const callback, void* user = nullptr) noexcept
|
||||
BufferDescriptor(void const* buffer, size_t size,
|
||||
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||
: buffer(const_cast<void*>(buffer)), size(size),
|
||||
mCallback(callback), mUser(user), mHandler(handler) {
|
||||
}
|
||||
@@ -122,9 +116,8 @@ public:
|
||||
*
|
||||
* @param buffer Memory address of the CPU buffer to reference
|
||||
* @param size Size of the CPU buffer in bytes
|
||||
* @param data A pointer to the data
|
||||
* @param handler Handler to use to dispatch the callback, or nullptr for the default handler
|
||||
* @return A new BufferDescriptor
|
||||
* @return a new BufferDescriptor
|
||||
*/
|
||||
template<typename T, void(T::*method)(void const*, size_t)>
|
||||
static BufferDescriptor make(void const* buffer, size_t size, T* data,
|
||||
@@ -171,7 +164,7 @@ public:
|
||||
* @param callback The new callback function
|
||||
* @param user An opaque user pointer passed to the callbeck function when it's called
|
||||
*/
|
||||
void setCallback(Callback const callback, void* user = nullptr) noexcept {
|
||||
void setCallback(Callback callback, void* user = nullptr) noexcept {
|
||||
this->mCallback = callback;
|
||||
this->mUser = user;
|
||||
this->mHandler = nullptr;
|
||||
@@ -183,7 +176,7 @@ public:
|
||||
* @param callback The new callback function
|
||||
* @param user An opaque user pointer passed to the callbeck function when it's called
|
||||
*/
|
||||
void setCallback(CallbackHandler* handler, Callback const callback, void* user = nullptr) noexcept {
|
||||
void setCallback(CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept {
|
||||
mCallback = callback;
|
||||
mUser = user;
|
||||
mHandler = handler;
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include <backend/DriverApiForward.h>
|
||||
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
|
||||
@@ -26,10 +28,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
namespace utils::io {
|
||||
class ostream;
|
||||
} // namespace utils::io
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
void* allocateFromCommandStream(DriverApi& driver, size_t size, size_t alignment) noexcept;
|
||||
|
||||
@@ -25,25 +25,23 @@
|
||||
#include <backend/PresentCallable.h>
|
||||
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/StaticString.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/ostream.h>
|
||||
#include <utils/StaticString.h>
|
||||
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include <string_view>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace utils::io {
|
||||
class ostream;
|
||||
} // namespace utils::io
|
||||
|
||||
/**
|
||||
* Types and enums used by filament's driver.
|
||||
*
|
||||
@@ -162,7 +160,7 @@ enum class TimerQueryResult : int8_t {
|
||||
AVAILABLE = 1, // result is available
|
||||
};
|
||||
|
||||
static constexpr const char* backendToString(Backend backend) {
|
||||
constexpr std::string_view to_string(Backend const backend) noexcept {
|
||||
switch (backend) {
|
||||
case Backend::NOOP:
|
||||
return "Noop";
|
||||
@@ -174,9 +172,11 @@ static constexpr const char* backendToString(Backend backend) {
|
||||
return "Metal";
|
||||
case Backend::WEBGPU:
|
||||
return "WebGPU";
|
||||
default:
|
||||
return "Unknown";
|
||||
case Backend::DEFAULT:
|
||||
return "Default";
|
||||
break;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +193,7 @@ enum class ShaderLanguage {
|
||||
WGSL = 5,
|
||||
};
|
||||
|
||||
static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) {
|
||||
constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) noexcept {
|
||||
switch (shaderLanguage) {
|
||||
case ShaderLanguage::ESSL1:
|
||||
return "ESSL 1.0";
|
||||
@@ -208,6 +208,7 @@ static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguag
|
||||
case ShaderLanguage::WGSL:
|
||||
return "WGSL";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
enum class ShaderStage : uint8_t {
|
||||
@@ -225,7 +226,7 @@ enum class ShaderStageFlags : uint8_t {
|
||||
ALL_SHADER_STAGE_FLAGS = VERTEX | FRAGMENT | COMPUTE
|
||||
};
|
||||
|
||||
static inline constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage type) noexcept {
|
||||
constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage type) noexcept {
|
||||
switch (type) {
|
||||
case ShaderStage::VERTEX:
|
||||
return bool(uint8_t(flags) & uint8_t(ShaderStageFlags::VERTEX));
|
||||
@@ -236,14 +237,114 @@ static inline constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage t
|
||||
}
|
||||
}
|
||||
|
||||
enum class DescriptorType : uint8_t {
|
||||
UNIFORM_BUFFER,
|
||||
SHADER_STORAGE_BUFFER,
|
||||
SAMPLER,
|
||||
INPUT_ATTACHMENT,
|
||||
SAMPLER_EXTERNAL
|
||||
enum class TextureType : uint8_t {
|
||||
FLOAT,
|
||||
INT,
|
||||
UINT,
|
||||
DEPTH,
|
||||
STENCIL,
|
||||
DEPTH_STENCIL
|
||||
};
|
||||
|
||||
constexpr std::string_view to_string(TextureType type) noexcept {
|
||||
switch (type) {
|
||||
case TextureType::FLOAT: return "FLOAT";
|
||||
case TextureType::INT: return "INT";
|
||||
case TextureType::UINT: return "UINT";
|
||||
case TextureType::DEPTH: return "DEPTH";
|
||||
case TextureType::STENCIL: return "STENCIL";
|
||||
case TextureType::DEPTH_STENCIL: return "DEPTH_STENCIL";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
enum class DescriptorType : uint8_t {
|
||||
SAMPLER_2D_FLOAT,
|
||||
SAMPLER_2D_INT,
|
||||
SAMPLER_2D_UINT,
|
||||
SAMPLER_2D_DEPTH,
|
||||
|
||||
SAMPLER_2D_ARRAY_FLOAT,
|
||||
SAMPLER_2D_ARRAY_INT,
|
||||
SAMPLER_2D_ARRAY_UINT,
|
||||
SAMPLER_2D_ARRAY_DEPTH,
|
||||
|
||||
SAMPLER_CUBE_FLOAT,
|
||||
SAMPLER_CUBE_INT,
|
||||
SAMPLER_CUBE_UINT,
|
||||
SAMPLER_CUBE_DEPTH,
|
||||
|
||||
SAMPLER_CUBE_ARRAY_FLOAT,
|
||||
SAMPLER_CUBE_ARRAY_INT,
|
||||
SAMPLER_CUBE_ARRAY_UINT,
|
||||
SAMPLER_CUBE_ARRAY_DEPTH,
|
||||
|
||||
SAMPLER_3D_FLOAT,
|
||||
SAMPLER_3D_INT,
|
||||
SAMPLER_3D_UINT,
|
||||
|
||||
SAMPLER_EXTERNAL,
|
||||
UNIFORM_BUFFER,
|
||||
SHADER_STORAGE_BUFFER,
|
||||
INPUT_ATTACHMENT,
|
||||
};
|
||||
|
||||
constexpr bool isDepthDescriptor(DescriptorType const type) noexcept {
|
||||
switch (type) {
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
return true;
|
||||
default: ;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr bool isFloatDescriptor(DescriptorType const type) noexcept {
|
||||
switch (type) {
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
return true;
|
||||
default: ;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr std::string_view to_string(DescriptorType type) noexcept {
|
||||
#define DESCRIPTOR_TYPE_CASE(TYPE) case DescriptorType::TYPE: return #TYPE;
|
||||
switch (type) {
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_FLOAT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_INT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_UINT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_DEPTH)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_FLOAT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_INT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_UINT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_DEPTH)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_FLOAT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_INT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_UINT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_DEPTH)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_FLOAT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_INT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_UINT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_DEPTH)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_FLOAT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_INT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_UINT)
|
||||
DESCRIPTOR_TYPE_CASE(SAMPLER_EXTERNAL)
|
||||
DESCRIPTOR_TYPE_CASE(UNIFORM_BUFFER)
|
||||
DESCRIPTOR_TYPE_CASE(SHADER_STORAGE_BUFFER)
|
||||
DESCRIPTOR_TYPE_CASE(INPUT_ATTACHMENT)
|
||||
}
|
||||
return "UNKNOWN";
|
||||
#undef DESCRIPTOR_TYPE_CASE
|
||||
}
|
||||
|
||||
enum class DescriptorFlags : uint8_t {
|
||||
NONE = 0x00,
|
||||
DYNAMIC_OFFSET = 0x01
|
||||
@@ -254,6 +355,13 @@ using descriptor_set_t = uint8_t;
|
||||
using descriptor_binding_t = uint8_t;
|
||||
|
||||
struct DescriptorSetLayoutBinding {
|
||||
static bool isSampler(DescriptorType type) noexcept {
|
||||
return int(type) <= int(DescriptorType::SAMPLER_EXTERNAL);
|
||||
}
|
||||
static bool isBuffer(DescriptorType type) noexcept {
|
||||
return type == DescriptorType::UNIFORM_BUFFER ||
|
||||
type == DescriptorType::SHADER_STORAGE_BUFFER;
|
||||
}
|
||||
DescriptorType type;
|
||||
ShaderStageFlags stageFlags;
|
||||
descriptor_binding_t binding;
|
||||
@@ -264,7 +372,7 @@ struct DescriptorSetLayoutBinding {
|
||||
// no uninitialized padding bytes.
|
||||
// uint8_t externalSamplerDataIndex = EXTERNAL_SAMPLER_DATA_INDEX_UNUSED;
|
||||
|
||||
friend inline bool operator==(DescriptorSetLayoutBinding const& lhs,
|
||||
friend bool operator==(DescriptorSetLayoutBinding const& lhs,
|
||||
DescriptorSetLayoutBinding const& rhs) noexcept {
|
||||
return lhs.type == rhs.type &&
|
||||
lhs.flags == rhs.flags &&
|
||||
@@ -297,7 +405,7 @@ enum class TargetBufferFlags : uint32_t {
|
||||
ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected.
|
||||
};
|
||||
|
||||
inline constexpr TargetBufferFlags getTargetBufferFlagsAt(size_t index) noexcept {
|
||||
constexpr TargetBufferFlags getTargetBufferFlagsAt(size_t index) noexcept {
|
||||
if (index == 0u) return TargetBufferFlags::COLOR0;
|
||||
if (index == 1u) return TargetBufferFlags::COLOR1;
|
||||
if (index == 2u) return TargetBufferFlags::COLOR2;
|
||||
@@ -454,6 +562,24 @@ enum class SamplerType : uint8_t {
|
||||
SAMPLER_CUBEMAP_ARRAY, //!< Cube map array texture (feature level 2)
|
||||
};
|
||||
|
||||
constexpr std::string_view to_string(SamplerType const type) noexcept {
|
||||
switch (type) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
return "SAMPLER_2D";
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
return "SAMPLER_2D_ARRAY";
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
return "SAMPLER_CUBEMAP";
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
return "SAMPLER_EXTERNAL";
|
||||
case SamplerType::SAMPLER_3D:
|
||||
return "SAMPLER_3D";
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
return "SAMPLER_CUBEMAP_ARRAY";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
//! Subpass type
|
||||
enum class SubpassType : uint8_t {
|
||||
SUBPASS_INPUT
|
||||
@@ -467,6 +593,20 @@ enum class SamplerFormat : uint8_t {
|
||||
SHADOW = 3 //!< shadow sampler (PCF)
|
||||
};
|
||||
|
||||
constexpr std::string_view to_string(SamplerFormat const format) noexcept {
|
||||
switch (format) {
|
||||
case SamplerFormat::INT:
|
||||
return "INT";
|
||||
case SamplerFormat::UINT:
|
||||
return "UINT";
|
||||
case SamplerFormat::FLOAT:
|
||||
return "FLOAT";
|
||||
case SamplerFormat::SHADOW:
|
||||
return "SHADOW";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported element types
|
||||
*/
|
||||
@@ -767,6 +907,8 @@ enum class TextureFormat : uint16_t {
|
||||
SRGB_ALPHA_BPTC_UNORM, // BC7 sRGB
|
||||
};
|
||||
|
||||
TextureType getTextureType(TextureFormat format) noexcept;
|
||||
|
||||
//! Bitmask describing the intended Texture Usage
|
||||
enum class TextureUsage : uint16_t {
|
||||
NONE = 0x0000,
|
||||
@@ -794,7 +936,7 @@ enum class TextureSwizzle : uint8_t {
|
||||
};
|
||||
|
||||
//! returns whether this format a depth format
|
||||
static constexpr bool isDepthFormat(TextureFormat format) noexcept {
|
||||
constexpr bool isDepthFormat(TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::DEPTH32F:
|
||||
case TextureFormat::DEPTH24:
|
||||
@@ -807,7 +949,7 @@ static constexpr bool isDepthFormat(TextureFormat format) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool isStencilFormat(TextureFormat format) noexcept {
|
||||
constexpr bool isStencilFormat(TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::STENCIL8:
|
||||
case TextureFormat::DEPTH24_STENCIL8:
|
||||
@@ -818,7 +960,7 @@ static constexpr bool isStencilFormat(TextureFormat format) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
inline constexpr bool isColorFormat(TextureFormat format) noexcept {
|
||||
constexpr bool isColorFormat(TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
// Standard color formats
|
||||
case TextureFormat::R8:
|
||||
@@ -845,7 +987,7 @@ inline constexpr bool isColorFormat(TextureFormat format) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr bool isUnsignedIntFormat(TextureFormat format) {
|
||||
constexpr bool isUnsignedIntFormat(TextureFormat format) {
|
||||
switch (format) {
|
||||
case TextureFormat::R8UI:
|
||||
case TextureFormat::R16UI:
|
||||
@@ -866,7 +1008,7 @@ static constexpr bool isUnsignedIntFormat(TextureFormat format) {
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool isSignedIntFormat(TextureFormat format) {
|
||||
constexpr bool isSignedIntFormat(TextureFormat format) {
|
||||
switch (format) {
|
||||
case TextureFormat::R8I:
|
||||
case TextureFormat::R16I:
|
||||
@@ -888,35 +1030,35 @@ static constexpr bool isSignedIntFormat(TextureFormat format) {
|
||||
}
|
||||
|
||||
//! returns whether this format is a compressed format
|
||||
static constexpr bool isCompressedFormat(TextureFormat format) noexcept {
|
||||
constexpr bool isCompressedFormat(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::EAC_R11;
|
||||
}
|
||||
|
||||
//! returns whether this format is an ETC2 compressed format
|
||||
static constexpr bool isETC2Compression(TextureFormat format) noexcept {
|
||||
constexpr bool isETC2Compression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::EAC_R11 && format <= TextureFormat::ETC2_EAC_SRGBA8;
|
||||
}
|
||||
|
||||
//! returns whether this format is an S3TC compressed format
|
||||
static constexpr bool isS3TCCompression(TextureFormat format) noexcept {
|
||||
constexpr bool isS3TCCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::DXT1_RGB && format <= TextureFormat::DXT5_SRGBA;
|
||||
}
|
||||
|
||||
static constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept {
|
||||
constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::DXT1_SRGB && format <= TextureFormat::DXT5_SRGBA;
|
||||
}
|
||||
|
||||
//! returns whether this format is an RGTC compressed format
|
||||
static constexpr bool isRGTCCompression(TextureFormat format) noexcept {
|
||||
constexpr bool isRGTCCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::RED_RGTC1 && format <= TextureFormat::SIGNED_RED_GREEN_RGTC2;
|
||||
}
|
||||
|
||||
//! returns whether this format is an BPTC compressed format
|
||||
static constexpr bool isBPTCCompression(TextureFormat format) noexcept {
|
||||
constexpr bool isBPTCCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::RGB_BPTC_SIGNED_FLOAT && format <= TextureFormat::SRGB_ALPHA_BPTC_UNORM;
|
||||
}
|
||||
|
||||
static constexpr bool isASTCCompression(TextureFormat format) noexcept {
|
||||
constexpr bool isASTCCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::RGBA_ASTC_4x4 && format <= TextureFormat::SRGB8_ALPHA8_ASTC_12x12;
|
||||
}
|
||||
|
||||
@@ -1041,15 +1183,19 @@ struct SamplerParams { // NOLINT
|
||||
}
|
||||
};
|
||||
|
||||
bool isFiltered() const noexcept {
|
||||
return filterMag != SamplerMagFilter::NEAREST || filterMin != SamplerMinFilter::NEAREST;
|
||||
}
|
||||
|
||||
private:
|
||||
friend inline bool operator == (SamplerParams lhs, SamplerParams rhs) noexcept {
|
||||
return SamplerParams::EqualTo{}(lhs, rhs);
|
||||
friend bool operator == (SamplerParams lhs, SamplerParams rhs) noexcept {
|
||||
return EqualTo{}(lhs, rhs);
|
||||
}
|
||||
friend inline bool operator != (SamplerParams lhs, SamplerParams rhs) noexcept {
|
||||
return !SamplerParams::EqualTo{}(lhs, rhs);
|
||||
friend bool operator != (SamplerParams lhs, SamplerParams rhs) noexcept {
|
||||
return !EqualTo{}(lhs, rhs);
|
||||
}
|
||||
friend inline bool operator < (SamplerParams lhs, SamplerParams rhs) noexcept {
|
||||
return SamplerParams::LessThan{}(lhs, rhs);
|
||||
friend bool operator < (SamplerParams lhs, SamplerParams rhs) noexcept {
|
||||
return LessThan{}(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1099,15 +1245,15 @@ struct SamplerYcbcrConversion {// NOLINT
|
||||
};
|
||||
|
||||
private:
|
||||
friend inline bool operator == (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
friend bool operator == (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
noexcept {
|
||||
return SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
|
||||
}
|
||||
friend inline bool operator != (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
friend bool operator != (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
noexcept {
|
||||
return !SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
|
||||
}
|
||||
friend inline bool operator < (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
friend bool operator < (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
noexcept {
|
||||
return SamplerYcbcrConversion::LessThan{}(lhs, rhs);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_HANDLE_H
|
||||
#define TNT_FILAMENT_BACKEND_HANDLE_H
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#include <utils/ostream.h>
|
||||
#endif
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <type_traits> // FIXME: STL headers are not allowed in public headers
|
||||
@@ -24,10 +27,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace utils::io {
|
||||
class ostream;
|
||||
} // namespace utils::io
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
struct HwBufferObject;
|
||||
|
||||
@@ -20,14 +20,12 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace utils::io {
|
||||
class ostream;
|
||||
} // namespace utils::io
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
//! \privatesection
|
||||
|
||||
@@ -24,14 +24,11 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace utils::io {
|
||||
class ostream;
|
||||
} // namespace utils::io
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
@@ -31,10 +33,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace utils::io {
|
||||
class ostream;
|
||||
} // namespace utils::io
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class Program {
|
||||
|
||||
@@ -19,26 +19,22 @@
|
||||
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <utility>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace utils::io {
|
||||
class ostream;
|
||||
} // namespace utils::io
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
//! \privatesection
|
||||
|
||||
struct TargetBufferInfo {
|
||||
// note: the parameters of this constructor are not in the order of this structure's fields
|
||||
TargetBufferInfo(Handle<HwTexture> handle, uint8_t const level, uint16_t const layer) noexcept
|
||||
: handle(std::move(handle)), level(level), layer(layer) {
|
||||
TargetBufferInfo(Handle<HwTexture> handle, uint8_t level, uint16_t layer) noexcept
|
||||
: handle(handle), level(level), layer(layer) {
|
||||
}
|
||||
|
||||
TargetBufferInfo(Handle<HwTexture> handle, uint8_t const level) noexcept
|
||||
TargetBufferInfo(Handle<HwTexture> handle, uint8_t level) noexcept
|
||||
: handle(handle), level(level) {
|
||||
}
|
||||
|
||||
@@ -74,11 +70,11 @@ private:
|
||||
TargetBufferInfo mInfos[MAX_SUPPORTED_RENDER_TARGET_COUNT];
|
||||
|
||||
public:
|
||||
TargetBufferInfo const& operator[](size_t const i) const noexcept {
|
||||
TargetBufferInfo const& operator[](size_t i) const noexcept {
|
||||
return mInfos[i];
|
||||
}
|
||||
|
||||
TargetBufferInfo& operator[](size_t const i) noexcept {
|
||||
TargetBufferInfo& operator[](size_t i) noexcept {
|
||||
return mInfos[i];
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,8 @@
|
||||
#include <utils/Hash.h>
|
||||
#include <utils/PrivateImplementation.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "DataReshaper.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/CString.h>
|
||||
|
||||
#include <string_view>
|
||||
@@ -223,6 +225,143 @@ size_t getFormatSize(TextureFormat format) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
TextureType getTextureType(TextureFormat const format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::UNUSED:
|
||||
// should not happen
|
||||
return TextureType::FLOAT;
|
||||
|
||||
case TextureFormat::R8:
|
||||
case TextureFormat::R16F:
|
||||
case TextureFormat::RG8:
|
||||
case TextureFormat::RGB565:
|
||||
case TextureFormat::RGB5_A1:
|
||||
case TextureFormat::RGBA4:
|
||||
case TextureFormat::R32F:
|
||||
case TextureFormat::RGB8:
|
||||
case TextureFormat::SRGB8:
|
||||
case TextureFormat::RG16F:
|
||||
case TextureFormat::R11F_G11F_B10F:
|
||||
case TextureFormat::RGB9_E5:
|
||||
case TextureFormat::RGBA8:
|
||||
case TextureFormat::SRGB8_A8:
|
||||
case TextureFormat::RGB10_A2:
|
||||
case TextureFormat::RGB16F:
|
||||
case TextureFormat::RG32F:
|
||||
case TextureFormat::RGBA16F:
|
||||
case TextureFormat::RGB32F:
|
||||
case TextureFormat::RGBA32F:
|
||||
return TextureType::FLOAT;
|
||||
|
||||
case TextureFormat::R8_SNORM:
|
||||
case TextureFormat::RG8_SNORM:
|
||||
case TextureFormat::RGB8_SNORM:
|
||||
case TextureFormat::RGBA8_SNORM:
|
||||
// SNORM are treated as float
|
||||
return TextureType::FLOAT;
|
||||
|
||||
case TextureFormat::R8UI:
|
||||
case TextureFormat::R16UI:
|
||||
case TextureFormat::RG8UI:
|
||||
case TextureFormat::RGB8UI:
|
||||
case TextureFormat::R32UI:
|
||||
case TextureFormat::RG16UI:
|
||||
case TextureFormat::RGBA8UI:
|
||||
case TextureFormat::RGB16UI:
|
||||
case TextureFormat::RG32UI:
|
||||
case TextureFormat::RGBA16UI:
|
||||
case TextureFormat::RGB32UI:
|
||||
case TextureFormat::RGBA32UI:
|
||||
return TextureType::UINT;
|
||||
|
||||
case TextureFormat::R8I:
|
||||
case TextureFormat::R16I:
|
||||
case TextureFormat::RG8I:
|
||||
case TextureFormat::RGB8I:
|
||||
case TextureFormat::R32I:
|
||||
case TextureFormat::RG16I:
|
||||
case TextureFormat::RGBA8I:
|
||||
case TextureFormat::RGB16I:
|
||||
case TextureFormat::RG32I:
|
||||
case TextureFormat::RGBA16I:
|
||||
case TextureFormat::RGB32I:
|
||||
case TextureFormat::RGBA32I:
|
||||
return TextureType::INT;
|
||||
|
||||
case TextureFormat::DEPTH16:
|
||||
case TextureFormat::DEPTH24:
|
||||
case TextureFormat::DEPTH32F:
|
||||
return TextureType::DEPTH;
|
||||
|
||||
case TextureFormat::STENCIL8:
|
||||
return TextureType::STENCIL;
|
||||
|
||||
case TextureFormat::DEPTH24_STENCIL8:
|
||||
case TextureFormat::DEPTH32F_STENCIL8:
|
||||
return TextureType::DEPTH_STENCIL;
|
||||
|
||||
// Compressed formats ---------------------------------------------------------------------
|
||||
|
||||
case TextureFormat::EAC_RG11:
|
||||
case TextureFormat::EAC_RG11_SIGNED:
|
||||
case TextureFormat::ETC2_EAC_RGBA8:
|
||||
case TextureFormat::ETC2_EAC_SRGBA8:
|
||||
case TextureFormat::EAC_R11:
|
||||
case TextureFormat::EAC_R11_SIGNED:
|
||||
case TextureFormat::ETC2_RGB8:
|
||||
case TextureFormat::ETC2_SRGB8:
|
||||
case TextureFormat::ETC2_RGB8_A1:
|
||||
case TextureFormat::ETC2_SRGB8_A1:
|
||||
case TextureFormat::DXT1_RGB:
|
||||
case TextureFormat::DXT1_RGBA:
|
||||
case TextureFormat::DXT1_SRGB:
|
||||
case TextureFormat::DXT1_SRGBA:
|
||||
case TextureFormat::DXT3_RGBA:
|
||||
case TextureFormat::DXT3_SRGBA:
|
||||
case TextureFormat::DXT5_RGBA:
|
||||
case TextureFormat::DXT5_SRGBA:
|
||||
case TextureFormat::RED_RGTC1:
|
||||
case TextureFormat::SIGNED_RED_RGTC1:
|
||||
case TextureFormat::RED_GREEN_RGTC2:
|
||||
case TextureFormat::SIGNED_RED_GREEN_RGTC2:
|
||||
case TextureFormat::RGB_BPTC_SIGNED_FLOAT:
|
||||
case TextureFormat::RGB_BPTC_UNSIGNED_FLOAT:
|
||||
case TextureFormat::RGBA_BPTC_UNORM:
|
||||
case TextureFormat::SRGB_ALPHA_BPTC_UNORM:
|
||||
case TextureFormat::RGBA_ASTC_4x4:
|
||||
case TextureFormat::RGBA_ASTC_5x4:
|
||||
case TextureFormat::RGBA_ASTC_5x5:
|
||||
case TextureFormat::RGBA_ASTC_6x5:
|
||||
case TextureFormat::RGBA_ASTC_6x6:
|
||||
case TextureFormat::RGBA_ASTC_8x5:
|
||||
case TextureFormat::RGBA_ASTC_8x6:
|
||||
case TextureFormat::RGBA_ASTC_8x8:
|
||||
case TextureFormat::RGBA_ASTC_10x5:
|
||||
case TextureFormat::RGBA_ASTC_10x6:
|
||||
case TextureFormat::RGBA_ASTC_10x8:
|
||||
case TextureFormat::RGBA_ASTC_10x10:
|
||||
case TextureFormat::RGBA_ASTC_12x10:
|
||||
case TextureFormat::RGBA_ASTC_12x12:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_4x4:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_5x4:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_5x5:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_6x5:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_6x6:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_8x5:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_8x6:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_8x8:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_10x5:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_10x6:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_10x8:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_10x10:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_12x10:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_12x12:
|
||||
return TextureType::FLOAT;
|
||||
}
|
||||
|
||||
return TextureType::FLOAT;
|
||||
}
|
||||
|
||||
size_t getFormatComponentCount(TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::R8:
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <utility>
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
#include "MetalContext.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
|
||||
@@ -672,22 +672,8 @@ void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
|
||||
// nothing to do, timer query was constructed in createTimerQueryS
|
||||
}
|
||||
|
||||
const char* toString(DescriptorType type) {
|
||||
switch (type) {
|
||||
case DescriptorType::UNIFORM_BUFFER:
|
||||
return "UNIFORM_BUFFER";
|
||||
case DescriptorType::SHADER_STORAGE_BUFFER:
|
||||
return "SHADER_STORAGE_BUFFER";
|
||||
case DescriptorType::SAMPLER:
|
||||
return "SAMPLER";
|
||||
case DescriptorType::INPUT_ATTACHMENT:
|
||||
return "INPUT_ATTACHMENT";
|
||||
case DescriptorType::SAMPLER_EXTERNAL:
|
||||
return "SAMPLER_EXTERNAL";
|
||||
}
|
||||
}
|
||||
|
||||
const char* toString(ShaderStageFlags flags) {
|
||||
UTILS_UNUSED
|
||||
static const char* toString(ShaderStageFlags flags) {
|
||||
std::vector<const char*> stages;
|
||||
if (any(flags & ShaderStageFlags::VERTEX)) {
|
||||
stages.push_back("VERTEX");
|
||||
@@ -721,25 +707,15 @@ const char* toString(DescriptorFlags flags) {
|
||||
|
||||
void MetalDriver::createDescriptorSetLayoutR(
|
||||
Handle<HwDescriptorSetLayout> dslh, DescriptorSetLayout&& info) {
|
||||
#if FILAMENT_METAL_DEBUG_LOG == 1
|
||||
const char* labelStr = "";
|
||||
std::visit([&labelStr](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, utils::CString> || std::is_same_v<T, utils::StaticString>) {
|
||||
labelStr = arg.c_str();
|
||||
}
|
||||
}, info.label);
|
||||
std::sort(info.bindings.begin(), info.bindings.end(),
|
||||
[](const auto& a, const auto& b) { return a.binding < b.binding; });
|
||||
DEBUG_LOG("createDescriptorSetLayoutR(dslh = %d, info = { label = %s,\n", dslh.getId(),
|
||||
labelStr);
|
||||
DEBUG_LOG("createDescriptorSetLayoutR(dslh = %d, info = {\n", dslh.getId());
|
||||
for (size_t i = 0; i < info.bindings.size(); i++) {
|
||||
DEBUG_LOG(" {binding = %d, type = %s, count = %d, stage = %s, flags = %s},\n",
|
||||
info.bindings[i].binding, toString(info.bindings[i].type), info.bindings[i].count,
|
||||
toString(info.bindings[i].stageFlags), toString(info.bindings[i].flags));
|
||||
}
|
||||
DEBUG_LOG("})\n");
|
||||
#endif
|
||||
construct_handle<MetalDescriptorSetLayout>(dslh, std::move(info));
|
||||
}
|
||||
|
||||
|
||||
@@ -1356,7 +1356,25 @@ id<MTLArgumentEncoder> MetalDescriptorSetLayout::getArgumentEncoderSlow(id<MTLDe
|
||||
[arguments addObject:bufferArgument];
|
||||
break;
|
||||
}
|
||||
case DescriptorType::SAMPLER:
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
case DescriptorType::SAMPLER_3D_UINT:
|
||||
case DescriptorType::SAMPLER_EXTERNAL: {
|
||||
MTLArgumentDescriptor* textureArgument = [MTLArgumentDescriptor argumentDescriptor];
|
||||
textureArgument.index = binding.binding * 2;
|
||||
@@ -1382,9 +1400,6 @@ id<MTLArgumentEncoder> MetalDescriptorSetLayout::getArgumentEncoderSlow(id<MTLDe
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (arguments.count == 0) {
|
||||
return nil;
|
||||
}
|
||||
return [device newArgumentEncoderWithArguments:arguments];
|
||||
}
|
||||
|
||||
@@ -1445,9 +1460,6 @@ id<MTLBuffer> MetalDescriptorSet::finalizeAndGetBuffer(MetalDriver* driver, Shad
|
||||
|
||||
id<MTLArgumentEncoder> encoder =
|
||||
layout->getArgumentEncoder(context.device, stage, textureTypes);
|
||||
if (!encoder) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
{
|
||||
ScopedAllocationTimer timer("descriptor_set");
|
||||
@@ -1478,7 +1490,25 @@ id<MTLBuffer> MetalDescriptorSet::finalizeAndGetBuffer(MetalDriver* driver, Shad
|
||||
atIndex:binding.binding * 2];
|
||||
break;
|
||||
}
|
||||
case DescriptorType::SAMPLER:
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
case DescriptorType::SAMPLER_3D_UINT:
|
||||
case DescriptorType::SAMPLER_EXTERNAL: {
|
||||
auto found = textures.find(binding.binding);
|
||||
if (found == textures.end()) {
|
||||
|
||||
@@ -20,18 +20,17 @@
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
#include "private/backend/Driver.h"
|
||||
#include "backend/Program.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Program.h>
|
||||
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Hash.h>
|
||||
#include <utils/Invocable.h>
|
||||
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
#include <memory>
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
#include <utils/Hash.h>
|
||||
#include <utils/Invocable.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
@@ -69,9 +69,8 @@ public:
|
||||
assert_invariant(set < MAX_DESCRIPTOR_SET_COUNT);
|
||||
assert_invariant(binding < MAX_DESCRIPTOR_COUNT);
|
||||
assert_invariant(entry.binding < 128); // we reserve 1 bit for the type right now
|
||||
mStorage[set][binding] = { (uint8_t)entry.binding,
|
||||
entry.type == DescriptorType::SAMPLER ||
|
||||
entry.type == DescriptorType::SAMPLER_EXTERNAL };
|
||||
mStorage[set][binding] = { uint8_t(entry.binding),
|
||||
DescriptorSetLayoutBinding::isSampler(entry.type) };
|
||||
mActiveDescriptors[set].set(binding);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,26 @@ GLDescriptorSet::GLDescriptorSet(OpenGLContext& gl, DescriptorSetLayoutHandle ds
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DescriptorType::SAMPLER:
|
||||
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
case DescriptorType::SAMPLER_3D_UINT:
|
||||
case DescriptorType::SAMPLER_EXTERNAL:
|
||||
if (UTILS_UNLIKELY(gl.isES2())) {
|
||||
desc.emplace<SamplerGLES2>();
|
||||
|
||||
@@ -542,13 +542,6 @@ void OpenGLContext::initBugs(Bugs* bugs, Extensions const& exts,
|
||||
} else if (strstr(renderer, "Intel")) {
|
||||
// Intel GPU
|
||||
bugs->vao_doesnt_store_element_array_buffer_binding = true;
|
||||
|
||||
if (strstr(renderer, "Mesa")) {
|
||||
// Mesa Intel driver on Linux/Android
|
||||
// Renderer of the form [Mesa Intel(R) HD Graphics 505 (APL 3)]
|
||||
// b/405252622
|
||||
bugs->disable_invalidate_framebuffer = true;
|
||||
}
|
||||
} else if (strstr(renderer, "PowerVR")) {
|
||||
// PowerVR GPU
|
||||
// On PowerVR (Rogue GE8320) glFlush doesn't seem to do anything, in particular,
|
||||
|
||||
@@ -175,7 +175,25 @@ void OpenGLProgram::initializeProgramState(OpenGLContext& context, GLuint progra
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DescriptorType::SAMPLER:
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
case DescriptorType::SAMPLER_3D_UINT:
|
||||
case DescriptorType::SAMPLER_EXTERNAL: {
|
||||
if (!entry.name.empty()) {
|
||||
GLint const loc = glGetUniformLocation(program, entry.name.c_str());
|
||||
|
||||
@@ -54,7 +54,7 @@ struct PlatformCocoaGLImpl {
|
||||
CVOpenGLTextureCacheRef mTextureCache = nullptr;
|
||||
std::unique_ptr<CocoaExternalImage::SharedGl> mExternalImageSharedGl;
|
||||
void updateOpenGLContext(NSView *nsView, bool resetView, bool clearView);
|
||||
struct ExternalImageCocoaGL final : public Platform::ExternalImage {
|
||||
struct ExternalImageCocoaGL : public Platform::ExternalImage {
|
||||
CVPixelBufferRef cvBuffer;
|
||||
protected:
|
||||
~ExternalImageCocoaGL() noexcept final;
|
||||
|
||||
@@ -93,7 +93,26 @@ BitmaskGroup fromBackendLayout(DescriptorSetLayout const& layout) {
|
||||
case DescriptorType::SAMPLER_EXTERNAL:
|
||||
fromStageFlags(binding.stageFlags, binding.binding, mask.externalSampler);
|
||||
UTILS_FALLTHROUGH;
|
||||
case DescriptorType::SAMPLER: {
|
||||
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
case DescriptorType::SAMPLER_3D_UINT: {
|
||||
fromStageFlags(binding.stageFlags, binding.binding, mask.sampler);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
|
||||
@@ -469,7 +469,7 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
mDevice, flags);
|
||||
assert_invariant(mSwapChain);
|
||||
WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(mDevice,
|
||||
mSwapChain->getColorFormat());
|
||||
mSwapChain->getColorFormat(), mSwapChain->getDepthFormat());
|
||||
FWGPU_LOGW << "WebGPU support is still essentially a no-op at this point in development (only "
|
||||
"background components have been instantiated/selected, such as surface/screen, "
|
||||
"graphics device/GPU, etc.), thus nothing is being drawn to the screen."
|
||||
@@ -591,7 +591,7 @@ void WebGPUDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh
|
||||
void WebGPUDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
Handle<HwDescriptorSetLayout> dslh) {
|
||||
auto layout = handleCast<WebGPUDescriptorSetLayout>(dslh);
|
||||
constructHandle<WebGPUDescriptorSet>(dsh, layout->getLayout(), layout->getBindGroupEntries());
|
||||
constructHandle<WebGPUDescriptorSet>(dsh, layout->getLayout(), layout->getBindGroupEntries(), layout->label);
|
||||
}
|
||||
|
||||
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream) {
|
||||
@@ -1069,97 +1069,98 @@ wgpu::Sampler WebGPUDriver::makeSampler(SamplerParams const& params) {
|
||||
desc.addressModeU = fWrapModeToWAddressMode(params.wrapS);
|
||||
desc.addressModeV = fWrapModeToWAddressMode(params.wrapR);
|
||||
desc.addressModeW = fWrapModeToWAddressMode(params.wrapT);
|
||||
switch (params.filterMag) {
|
||||
case SamplerMagFilter::NEAREST: {
|
||||
desc.magFilter = wgpu::FilterMode::Nearest;
|
||||
break;
|
||||
if (params.compareMode == SamplerCompareMode::COMPARE_TO_TEXTURE) {
|
||||
switch (params.filterMag) {
|
||||
case SamplerMagFilter::NEAREST: {
|
||||
desc.magFilter = wgpu::FilterMode::Nearest;
|
||||
break;
|
||||
}
|
||||
case SamplerMagFilter::LINEAR: {
|
||||
desc.magFilter = wgpu::FilterMode::Linear;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case SamplerMagFilter::LINEAR: {
|
||||
desc.magFilter = wgpu::FilterMode::Linear;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (params.filterMin) {
|
||||
case SamplerMinFilter::NEAREST: {
|
||||
desc.minFilter = wgpu::FilterMode::Nearest;
|
||||
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
|
||||
// suffice
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::LINEAR: {
|
||||
desc.minFilter = wgpu::FilterMode::Linear;
|
||||
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
|
||||
// suffice
|
||||
switch (params.filterMin) {
|
||||
case SamplerMinFilter::NEAREST: {
|
||||
desc.minFilter = wgpu::FilterMode::Nearest;
|
||||
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
|
||||
// suffice
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Undefined;
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::LINEAR: {
|
||||
desc.minFilter = wgpu::FilterMode::Linear;
|
||||
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
|
||||
// suffice
|
||||
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST: {
|
||||
desc.minFilter = wgpu::FilterMode::Nearest;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST: {
|
||||
desc.minFilter = wgpu::FilterMode::Linear;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Undefined;
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST: {
|
||||
desc.minFilter = wgpu::FilterMode::Nearest;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST: {
|
||||
desc.minFilter = wgpu::FilterMode::Linear;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
|
||||
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR: {
|
||||
desc.minFilter = wgpu::FilterMode::Nearest;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR: {
|
||||
desc.minFilter = wgpu::FilterMode::Nearest;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR: {
|
||||
desc.minFilter = wgpu::FilterMode::Linear;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR: {
|
||||
desc.minFilter = wgpu::FilterMode::Linear;
|
||||
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (params.compareFunc) {
|
||||
case SamplerCompareFunc::LE: {
|
||||
desc.compare = wgpu::CompareFunction::LessEqual;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::GE: {
|
||||
desc.compare = wgpu::CompareFunction::GreaterEqual;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::L: {
|
||||
desc.compare = wgpu::CompareFunction::Less;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::G: {
|
||||
desc.compare = wgpu::CompareFunction::Greater;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::E: {
|
||||
desc.compare = wgpu::CompareFunction::Equal;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::NE: {
|
||||
desc.compare = wgpu::CompareFunction::NotEqual;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::A: {
|
||||
desc.compare = wgpu::CompareFunction::Always;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::N: {
|
||||
desc.compare = wgpu::CompareFunction::Never;
|
||||
break;
|
||||
switch (params.compareFunc) {
|
||||
case SamplerCompareFunc::LE: {
|
||||
desc.compare = wgpu::CompareFunction::LessEqual;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::GE: {
|
||||
desc.compare = wgpu::CompareFunction::GreaterEqual;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::L: {
|
||||
desc.compare = wgpu::CompareFunction::Less;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::G: {
|
||||
desc.compare = wgpu::CompareFunction::Greater;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::E: {
|
||||
desc.compare = wgpu::CompareFunction::Equal;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::NE: {
|
||||
desc.compare = wgpu::CompareFunction::NotEqual;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::A: {
|
||||
desc.compare = wgpu::CompareFunction::Always;
|
||||
break;
|
||||
}
|
||||
case SamplerCompareFunc::N: {
|
||||
desc.compare = wgpu::CompareFunction::Never;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
desc.maxAnisotropy = 1u << params.anisotropyLog2;
|
||||
|
||||
|
||||
// Unused: Filament's compareMode, WGPU lodMinClamp/lodMaxClamp
|
||||
// Unused: WGPU lodMinClamp/lodMaxClamp
|
||||
|
||||
//TODO Once we can properly map to descriptorsetlayout use the sampler.
|
||||
return mDevice.CreateSampler(/*&desc*/);
|
||||
return mDevice.CreateSampler(&desc);
|
||||
}
|
||||
wgpu::AddressMode WebGPUDriver::fWrapModeToWAddressMode(const SamplerWrapMode& fWrapMode) {
|
||||
switch (fWrapMode) {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
@@ -248,6 +247,7 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
const auto& temp = std::get_if<utils::CString>(&layout.label);
|
||||
baseLabel = temp->c_str();
|
||||
}
|
||||
label = baseLabel;
|
||||
|
||||
// TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
|
||||
// debugging. For now, hack an incrementing value.
|
||||
@@ -255,8 +255,7 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
|
||||
unsigned int samplerCount =
|
||||
std::count_if(layout.bindings.begin(), layout.bindings.end(), [](auto& fEntry) {
|
||||
return fEntry.type == DescriptorType::SAMPLER ||
|
||||
fEntry.type == DescriptorType::SAMPLER_EXTERNAL;
|
||||
return DescriptorSetLayoutBinding::isSampler(fEntry.type);
|
||||
});
|
||||
|
||||
|
||||
@@ -270,12 +269,31 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
wEntry.visibility = filamentStageToWGPUStage(fEntry.stageFlags);
|
||||
wEntry.binding = fEntry.binding * 2;
|
||||
entryInfo.binding = wEntry.binding;
|
||||
wgpu::BindGroupLayoutEntry* sEntry;
|
||||
|
||||
switch (fEntry.type) {
|
||||
case DescriptorType::SAMPLER_EXTERNAL:
|
||||
case DescriptorType::SAMPLER: {
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
case DescriptorType::SAMPLER_3D_UINT: {
|
||||
auto& samplerEntry = wEntries.emplace_back();
|
||||
auto& samplerEntryInfo = mBindGroupEntries.emplace_back();
|
||||
sEntry = &samplerEntry;
|
||||
samplerEntry.binding = fEntry.binding * 2 + 1;
|
||||
samplerEntryInfo.binding = samplerEntry.binding;
|
||||
samplerEntryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::SAMPLER;
|
||||
@@ -283,15 +301,6 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
// We are simply hoping that undefined and defaults suffices here.
|
||||
samplerEntry.sampler.type = wgpu::SamplerBindingType::NonFiltering; // Example default
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Float; // Example default
|
||||
// TODO: FIX! THIS IS HACK FOR HELLO-TRIANGLE!
|
||||
if (baseLabel.find("Skybox") != std::string::npos ||
|
||||
(baseLabel == "Filament Default Material_perView" && wEntry.binding == 22)) {
|
||||
wEntry.texture.viewDimension = wgpu::TextureViewDimension::Cube;
|
||||
} else {
|
||||
wEntry.texture.viewDimension =
|
||||
wgpu::TextureViewDimension::e2D;// Example default
|
||||
}
|
||||
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW;
|
||||
break;
|
||||
}
|
||||
case DescriptorType::UNIFORM_BUFFER: {
|
||||
@@ -311,6 +320,81 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
PANIC_POSTCONDITION("Shader storage is not supported");
|
||||
break;
|
||||
}
|
||||
case DescriptorType::SAMPLER_EXTERNAL: {
|
||||
PANIC_POSTCONDITION("External Sampler is not supported");
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (fEntry.type) {
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e2D;
|
||||
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2D;
|
||||
break;
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e2DArray;
|
||||
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2DA;
|
||||
break;
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
wEntry.texture.viewDimension = wgpu::TextureViewDimension::Cube;
|
||||
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBE;
|
||||
break;
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
wEntry.texture.viewDimension = wgpu::TextureViewDimension::CubeArray;
|
||||
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBEA;
|
||||
break;
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
case DescriptorType::SAMPLER_3D_UINT:
|
||||
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e3D;
|
||||
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_3D;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (fEntry.type) {
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::UnfilterableFloat;
|
||||
break;
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Sint;
|
||||
break;
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_3D_UINT:
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Uint;
|
||||
break;
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
//Dummies complain if you set this correctly without having an associated dummy
|
||||
wEntry.texture.sampleType = wgpu::TextureSampleType::Depth;
|
||||
sEntry->sampler.type = wgpu::SamplerBindingType::Comparison;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// fEntry.count is unused currently
|
||||
}
|
||||
@@ -326,12 +410,12 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
WebGPUDescriptorSetLayout::~WebGPUDescriptorSetLayout() {}
|
||||
|
||||
wgpu::Buffer WebGPUDescriptorSet::sDummyUniformBuffer = nullptr;
|
||||
wgpu::Texture WebGPUDescriptorSet::sDummyTexture = nullptr;
|
||||
wgpu::TextureView WebGPUDescriptorSet::sDummyTextureView = nullptr;
|
||||
std::unordered_map<wgpu::TextureDimension, wgpu::Texture> WebGPUDescriptorSet::sDummyTextureMap;
|
||||
std::unordered_map<wgpu::TextureViewDimension, wgpu::TextureView> WebGPUDescriptorSet::sDummyTextureViewMap;
|
||||
wgpu::Sampler WebGPUDescriptorSet::sDummySampler = nullptr;
|
||||
|
||||
void WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(wgpu::Device const& device,
|
||||
wgpu::TextureFormat aColorFormat) {
|
||||
wgpu::TextureFormat aColorFormat, wgpu::TextureFormat aDepthFormat) {
|
||||
if (!sDummyUniformBuffer) {
|
||||
wgpu::BufferDescriptor bufferDescriptor{
|
||||
.label = "dummy_uniform_not_to_be_used",
|
||||
@@ -342,31 +426,75 @@ void WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(wgpu::Device cons
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer)
|
||||
<< "Failed to create dummy uniform buffer?";
|
||||
}
|
||||
if (!sDummyTexture || !sDummyTextureView) {
|
||||
if (sDummyTextureMap.empty() || sDummyTextureViewMap.empty()) {
|
||||
wgpu::TextureDescriptor textureDescriptor{
|
||||
.label = "dummy_texture_not_to_be_used",
|
||||
.usage = wgpu::TextureUsage::TextureBinding,
|
||||
.dimension = wgpu::TextureDimension::e2D,
|
||||
.size = wgpu::Extent3D{ .width = 4, .height = 4, .depthOrArrayLayers = 1 },
|
||||
.format = aColorFormat,
|
||||
// .viewFormatCount = 1,
|
||||
// .viewFormats = &aDepthFormat
|
||||
};
|
||||
if (!sDummyTexture) {
|
||||
sDummyTexture = device.CreateTexture(&textureDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer) << "Failed to create dummy texture?";
|
||||
}
|
||||
if (!sDummyTextureView) {
|
||||
wgpu::TextureViewDescriptor textureViewDescriptor{
|
||||
.label = "dummy_texture_view_not_to_be_used"
|
||||
};
|
||||
sDummyTextureView = sDummyTexture.CreateView(&textureViewDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer)
|
||||
<< "Failed to create dummy texture view?";
|
||||
}
|
||||
sDummyTextureMap[wgpu::TextureDimension::e2D] = device.CreateTexture(&textureDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e2D])
|
||||
<< "Failed to create dummy texture 2D?";
|
||||
textureDescriptor.dimension = wgpu::TextureDimension::e3D;
|
||||
sDummyTextureMap[wgpu::TextureDimension::e3D] = device.CreateTexture(&textureDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e3D])
|
||||
<< "Failed to create dummy texture 3D?";
|
||||
|
||||
//Hacking as an experiment, treating 1D as cube arbitrarilly since my map key was bad idea
|
||||
textureDescriptor.dimension = wgpu::TextureDimension::e2D;
|
||||
textureDescriptor.size.depthOrArrayLayers = 6;
|
||||
sDummyTextureMap[wgpu::TextureDimension::e1D] = device.CreateTexture(&textureDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e1D])
|
||||
<< "Failed to create dummy texture 3D?";
|
||||
|
||||
|
||||
wgpu::TextureViewDescriptor textureViewDescriptor{
|
||||
.label = "dummy_texture_view_not_to_be_used",
|
||||
};
|
||||
|
||||
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
|
||||
sDummyTextureViewMap[wgpu::TextureViewDimension::e2D] =
|
||||
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2D])
|
||||
<< "Failed to create dummy texture view?";
|
||||
|
||||
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray] =
|
||||
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2D])
|
||||
<< "Failed to create dummy texture view?";
|
||||
|
||||
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray] =
|
||||
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray])
|
||||
<< "Failed to create dummy texture view?";
|
||||
|
||||
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e3D;
|
||||
sDummyTextureViewMap[wgpu::TextureViewDimension::e3D] =
|
||||
sDummyTextureMap[wgpu::TextureDimension::e3D].CreateView(&textureViewDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e3D])
|
||||
<< "Failed to create dummy texture view?";
|
||||
|
||||
textureViewDescriptor.arrayLayerCount = 6;
|
||||
textureViewDescriptor.dimension = wgpu::TextureViewDimension::Cube;
|
||||
sDummyTextureViewMap[wgpu::TextureViewDimension::Cube] =
|
||||
sDummyTextureMap[wgpu::TextureDimension::e1D].CreateView(&textureViewDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::Cube])
|
||||
<< "Failed to create dummy texture view?";
|
||||
|
||||
textureViewDescriptor.dimension = wgpu::TextureViewDimension::CubeArray;
|
||||
sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray] =
|
||||
sDummyTextureMap[wgpu::TextureDimension::e1D].CreateView(&textureViewDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray])
|
||||
<< "Failed to create dummy texture view?";
|
||||
}
|
||||
if (!sDummySampler) {
|
||||
wgpu::SamplerDescriptor samplerDescriptor{
|
||||
.label = "dummy_sampler_not_to_be_used"
|
||||
};
|
||||
wgpu::SamplerDescriptor samplerDescriptor{ .label = "dummy_sampler_not_to_be_used" , .addressModeU = wgpu::AddressMode::MirrorRepeat};
|
||||
sDummySampler = device.CreateSampler(&samplerDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer) << "Failed to create dummy sampler?";
|
||||
}
|
||||
@@ -378,12 +506,12 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
|
||||
assert_invariant(WebGPUDescriptorSet::sDummyUniformBuffer &&
|
||||
"Dummy uniform buffer must have been created before "
|
||||
"creating dummy bind group entries.");
|
||||
assert_invariant(
|
||||
/* assert_invariant(
|
||||
WebGPUDescriptorSet::sDummyTexture &&
|
||||
"Dummy texture must have been created before creating dummy bind group entries.");
|
||||
assert_invariant(
|
||||
WebGPUDescriptorSet::sDummyTextureView &&
|
||||
"Dummy texture view must have been created before creating dummy bind group entries.");
|
||||
"Dummy texture view must have been created before creating dummy bind group entries.");*/
|
||||
assert_invariant(
|
||||
WebGPUDescriptorSet::sDummySampler &&
|
||||
"Dummy sampler must have been created before creating dummy bind group entries.");
|
||||
@@ -395,14 +523,31 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
|
||||
entry.binding = entryInfo.binding;
|
||||
switch (entryInfo.type) {
|
||||
case WebGPUDescriptorSetLayout::BindGroupEntryType::UNIFORM_BUFFER:
|
||||
entry.buffer = WebGPUDescriptorSet::sDummyUniformBuffer;
|
||||
break;
|
||||
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW:
|
||||
entry.textureView = WebGPUDescriptorSet::sDummyTextureView;
|
||||
//entry.buffer = WebGPUDescriptorSet::sDummyUniformBuffer;
|
||||
break;
|
||||
case WebGPUDescriptorSetLayout::BindGroupEntryType::SAMPLER:
|
||||
entry.sampler = WebGPUDescriptorSet::sDummySampler;
|
||||
// entry.sampler = WebGPUDescriptorSet::sDummySampler;
|
||||
break;
|
||||
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2D:
|
||||
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e2D];
|
||||
break;
|
||||
|
||||
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2DA:
|
||||
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray];
|
||||
break;
|
||||
|
||||
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBE:
|
||||
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::Cube];
|
||||
break;
|
||||
|
||||
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBEA:
|
||||
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray];
|
||||
break;
|
||||
|
||||
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_3D:
|
||||
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e3D];
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
std::sort(entries.begin(), entries.end(),
|
||||
@@ -413,9 +558,10 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
|
||||
}
|
||||
|
||||
WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
|
||||
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries)
|
||||
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries, std::string label)
|
||||
: mLayout(layout),
|
||||
mEntriesSortedByBinding(createDummyEntriesSortedByBinding(bindGroupEntries)) {
|
||||
bglLabel = label;
|
||||
// Establish the size of entries based on the layout. This should be reliable and efficient.
|
||||
assert_invariant(INVALID_INDEX > mEntryIndexByBinding.size());
|
||||
for (size_t i = 0; i < mEntryIndexByBinding.size(); i++) {
|
||||
@@ -450,6 +596,20 @@ wgpu::BindGroup WebGPUDescriptorSet::lockAndReturn(const wgpu::Device& device) {
|
||||
.entryCount = mEntriesSortedByBinding.size(),
|
||||
.entries = mEntriesSortedByBinding.data()
|
||||
};
|
||||
for(auto e : mEntriesSortedByBinding){
|
||||
if(e.sampler.Get() == sDummySampler.Get()){
|
||||
printf("===R Dummy %s UBO %i\n", bglLabel.c_str(), e.binding/2);
|
||||
}
|
||||
for(auto dt : sDummyTextureViewMap){
|
||||
if(e.textureView.Get() == dt.second.Get())
|
||||
{
|
||||
printf("===R Dummy %s Tex %i\n", bglLabel.c_str(), e.binding/2);
|
||||
}
|
||||
}
|
||||
if(e.buffer.Get() == sDummyUniformBuffer.Get()){
|
||||
printf("===R Dummy %s Sam %i\n", bglLabel.c_str(),(e.binding-1)/2);
|
||||
}
|
||||
}
|
||||
mBindGroup = device.CreateBindGroup(&desc);
|
||||
FILAMENT_CHECK_POSTCONDITION(mBindGroup) << "Failed to create bind group?";
|
||||
// once we have created the bind group itself we should no longer need any other state
|
||||
@@ -503,6 +663,7 @@ size_t WebGPUDescriptorSet::countEntitiesWithDynamicOffsets() const {
|
||||
return mEntriesByBindingWithDynamicOffsets.count();
|
||||
}
|
||||
|
||||
// From createTextureR
|
||||
WGPUTexture::WGPUTexture(SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples,
|
||||
uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage,
|
||||
wgpu::Device const& device) noexcept {
|
||||
@@ -516,7 +677,6 @@ WGPUTexture::WGPUTexture(SamplerType target, uint8_t levels, TextureFormat forma
|
||||
// First, the texture aspect, starting with the defaults/basic configuration
|
||||
mUsage = fToWGPUTextureUsage(usage);
|
||||
mFormat = fToWGPUTextureFormat(format);
|
||||
mAspect = fToWGPUTextureViewAspect(usage, format);
|
||||
wgpu::TextureDescriptor textureDescriptor{
|
||||
.label = getUserTextureLabel(target),
|
||||
.usage = mUsage,
|
||||
@@ -561,12 +721,13 @@ WGPUTexture::WGPUTexture(SamplerType target, uint8_t levels, TextureFormat forma
|
||||
mTexView = makeTextureView(0, levels, target);
|
||||
}
|
||||
|
||||
// From createTextureViewR
|
||||
WGPUTexture::WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept {
|
||||
mTexture = src->mTexture;
|
||||
mTexView = makeTextureView(baseLevel, levelCount, target);
|
||||
}
|
||||
|
||||
wgpu::TextureUsage WGPUTexture::fToWGPUTextureUsage(TextureUsage const& fUsage) {
|
||||
wgpu::TextureUsage WGPUTexture::fToWGPUTextureUsage(const TextureUsage& fUsage) {
|
||||
wgpu::TextureUsage retUsage = wgpu::TextureUsage::None;
|
||||
|
||||
// Basing this mapping off of VulkanTexture.cpp's getUsage func and suggestions from Gemini
|
||||
@@ -614,9 +775,8 @@ wgpu::TextureUsage WGPUTexture::fToWGPUTextureUsage(TextureUsage const& fUsage)
|
||||
// PROTECTED
|
||||
return retUsage;
|
||||
}
|
||||
|
||||
wgpu::TextureFormat WGPUTexture::fToWGPUTextureFormat(TextureFormat const& fFormat) {
|
||||
switch (fFormat) {
|
||||
wgpu::TextureFormat WGPUTexture::fToWGPUTextureFormat(const TextureFormat& fUsage) {
|
||||
switch (fUsage) {
|
||||
case filament::backend::TextureFormat::R8:
|
||||
return wgpu::TextureFormat::R8Unorm;
|
||||
case filament::backend::TextureFormat::R8_SNORM:
|
||||
@@ -855,57 +1015,24 @@ wgpu::TextureFormat WGPUTexture::fToWGPUTextureFormat(TextureFormat const& fForm
|
||||
}
|
||||
}
|
||||
|
||||
wgpu::TextureAspect WGPUTexture::fToWGPUTextureViewAspect(TextureUsage const& fUsage,
|
||||
TextureFormat const& fFormat) {
|
||||
|
||||
const bool isDepth = any(fUsage & TextureUsage::DEPTH_ATTACHMENT);
|
||||
const bool isStencil = any(fUsage & TextureUsage::STENCIL_ATTACHMENT);
|
||||
const bool isColor = any(fUsage & TextureUsage::COLOR_ATTACHMENT);
|
||||
const bool isSample = (fUsage == TextureUsage::SAMPLEABLE);
|
||||
|
||||
if (isDepth && !isColor && !isStencil) {
|
||||
return wgpu::TextureAspect::DepthOnly;
|
||||
}
|
||||
|
||||
if (isStencil && !isColor && !isDepth) {
|
||||
return wgpu::TextureAspect::StencilOnly;
|
||||
}
|
||||
|
||||
if (fFormat == filament::backend::TextureFormat::DEPTH32F ||
|
||||
fFormat == filament::backend::TextureFormat::DEPTH24 ||
|
||||
fFormat == filament::backend::TextureFormat::DEPTH16) {
|
||||
return wgpu::TextureAspect::DepthOnly;
|
||||
}
|
||||
|
||||
if (fFormat == filament::backend::TextureFormat::STENCIL8) {
|
||||
return wgpu::TextureAspect::StencilOnly;
|
||||
}
|
||||
|
||||
if (fFormat == filament::backend::TextureFormat::DEPTH24_STENCIL8 ||
|
||||
fFormat == filament::backend::TextureFormat::DEPTH32F_STENCIL8) {
|
||||
if (isSample) {
|
||||
return wgpu::TextureAspect::DepthOnly;
|
||||
}
|
||||
}
|
||||
|
||||
return wgpu::TextureAspect::All;
|
||||
}
|
||||
|
||||
wgpu::TextureView WGPUTexture::makeTextureView(const uint8_t& baseLevel, const uint8_t& levelCount,
|
||||
SamplerType target) {
|
||||
|
||||
// starting with the defaults/basic configuration
|
||||
wgpu::TextureViewDescriptor textureViewDescriptor{
|
||||
.label = getUserTextureViewLabel(target),
|
||||
.format = mFormat,
|
||||
// dimension depends on target and is set below
|
||||
.baseMipLevel = baseLevel,
|
||||
.mipLevelCount = levelCount,
|
||||
// TODO: check if this baseArrayLayer assumption is correct
|
||||
// baseArrayLayer is required, making a guess
|
||||
.baseArrayLayer = 0,
|
||||
.arrayLayerCount = mArrayLayerCount,
|
||||
.aspect = mAspect,
|
||||
// Have not found an analog to aspect in other drivers, but ALL should be unrestrictive.
|
||||
// TODO Can we make this better?
|
||||
.aspect = wgpu::TextureAspect::All,
|
||||
.usage = mUsage
|
||||
};
|
||||
|
||||
// adjust for specific cases
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
|
||||
|
||||
@@ -74,8 +74,8 @@ public:
|
||||
|
||||
private:
|
||||
// TODO: can we do better in terms on heap management.
|
||||
std::vector<wgpu::VertexBufferLayout> mVertexBufferLayout{};
|
||||
std::vector<std::vector<wgpu::VertexAttribute>> mAttributes{};
|
||||
std::vector<wgpu::VertexBufferLayout> mVertexBufferLayout {};
|
||||
std::vector<std::vector<wgpu::VertexAttribute>> mAttributes {};
|
||||
};
|
||||
|
||||
struct WGPUVertexBuffer : public HwVertexBuffer {
|
||||
@@ -103,10 +103,15 @@ struct WGPUBufferObject : HwBufferObject {
|
||||
|
||||
class WebGPUDescriptorSetLayout final : public HwDescriptorSetLayout {
|
||||
public:
|
||||
std::string label;
|
||||
|
||||
enum class BindGroupEntryType : uint8_t {
|
||||
UNIFORM_BUFFER,
|
||||
TEXTURE_VIEW,
|
||||
TEXTURE_VIEW_2D,
|
||||
TEXTURE_VIEW_2DA,
|
||||
TEXTURE_VIEW_CUBE,
|
||||
TEXTURE_VIEW_CUBEA,
|
||||
TEXTURE_VIEW_3D,
|
||||
SAMPLER
|
||||
};
|
||||
|
||||
@@ -133,11 +138,13 @@ private:
|
||||
|
||||
class WebGPUDescriptorSet final : public HwDescriptorSet {
|
||||
public:
|
||||
std::string bglLabel;
|
||||
static void initializeDummyResourcesIfNotAlready(wgpu::Device const&,
|
||||
wgpu::TextureFormat aColorFormat);
|
||||
wgpu::TextureFormat aColorFormat,
|
||||
wgpu::TextureFormat aDepthFormat);
|
||||
|
||||
WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
|
||||
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries);
|
||||
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries, std::string label);
|
||||
~WebGPUDescriptorSet();
|
||||
|
||||
wgpu::BindGroup lockAndReturn(wgpu::Device const&);
|
||||
@@ -145,11 +152,11 @@ public:
|
||||
[[nodiscard]] uint32_t const* setDynamicOffsets(uint32_t const* offsets);
|
||||
[[nodiscard]] bool getIsLocked() const { return mBindGroup != nullptr; }
|
||||
[[nodiscard]] size_t countEntitiesWithDynamicOffsets() const;
|
||||
|
||||
private:
|
||||
|
||||
static wgpu::Buffer sDummyUniformBuffer;
|
||||
static wgpu::Texture sDummyTexture;
|
||||
static wgpu::TextureView sDummyTextureView;
|
||||
static std::unordered_map<wgpu::TextureDimension, wgpu::Texture> sDummyTextureMap;
|
||||
static std::unordered_map<wgpu::TextureViewDimension, wgpu::TextureView> sDummyTextureViewMap;
|
||||
static wgpu::Sampler sDummySampler;
|
||||
|
||||
static std::vector<wgpu::BindGroupEntry> createDummyEntriesSortedByBinding(
|
||||
@@ -161,10 +168,10 @@ private:
|
||||
// Also storing the wgpu ObjectBase takes care of ownership challenges in theory
|
||||
wgpu::BindGroupLayout mLayout = nullptr;
|
||||
static constexpr uint8_t INVALID_INDEX = MAX_DESCRIPTOR_COUNT + 1;
|
||||
std::array<uint8_t, MAX_DESCRIPTOR_COUNT> mEntryIndexByBinding{};
|
||||
std::array<uint8_t, MAX_DESCRIPTOR_COUNT> mEntryIndexByBinding {};
|
||||
std::vector<wgpu::BindGroupEntry> mEntriesSortedByBinding;
|
||||
std::bitset<MAX_DESCRIPTOR_COUNT> mEntriesByBindingWithDynamicOffsets{};
|
||||
std::bitset<MAX_DESCRIPTOR_COUNT> mEntriesByBindingAdded{};
|
||||
std::bitset<MAX_DESCRIPTOR_COUNT> mEntriesByBindingWithDynamicOffsets {};
|
||||
std::bitset<MAX_DESCRIPTOR_COUNT> mEntriesByBindingAdded {};
|
||||
std::vector<uint32_t> mDynamicOffsets;
|
||||
wgpu::BindGroup mBindGroup = nullptr;
|
||||
};
|
||||
@@ -177,14 +184,11 @@ public:
|
||||
|
||||
WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept;
|
||||
|
||||
[[nodiscard]] const wgpu::Texture& getTexture() const { return mTexture; }
|
||||
[[nodiscard]] const wgpu::TextureView& getTexView() const { return mTexView; }
|
||||
const wgpu::Texture& getTexture() const { return mTexture; }
|
||||
const wgpu::TextureView& getTexView() const { return mTexView; }
|
||||
|
||||
static wgpu::TextureFormat fToWGPUTextureFormat(
|
||||
filament::backend::TextureFormat const& fFormat);
|
||||
static wgpu::TextureAspect fToWGPUTextureViewAspect(
|
||||
filament::backend::TextureUsage const& fUsage,
|
||||
filament::backend::TextureFormat const& fFormat);
|
||||
// Public to allow checking for support of a texture format
|
||||
static wgpu::TextureFormat fToWGPUTextureFormat(const filament::backend::TextureFormat& fUsage);
|
||||
|
||||
private:
|
||||
wgpu::TextureView makeTextureView(const uint8_t& baseLevel, const uint8_t& levelCount,
|
||||
@@ -195,10 +199,9 @@ private:
|
||||
wgpu::Texture mTexture = nullptr;
|
||||
wgpu::TextureUsage mUsage = wgpu::TextureUsage::None;
|
||||
wgpu::TextureFormat mFormat = wgpu::TextureFormat::Undefined;
|
||||
wgpu::TextureAspect mAspect = wgpu::TextureAspect::Undefined;
|
||||
uint32_t mArrayLayerCount = 1;
|
||||
wgpu::TextureView mTexView = nullptr;
|
||||
wgpu::TextureUsage fToWGPUTextureUsage(filament::backend::TextureUsage const& fUsage);
|
||||
wgpu::TextureUsage fToWGPUTextureUsage(const filament::backend::TextureUsage& fUsage);
|
||||
};
|
||||
|
||||
struct WGPURenderPrimitive : public HwRenderPrimitive {
|
||||
@@ -256,7 +259,7 @@ private:
|
||||
|
||||
Attachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
|
||||
math::uint2 attachmentSize = {};
|
||||
std::vector<wgpu::RenderPassColorAttachment> colorAttachments{};
|
||||
std::vector<wgpu::RenderPassColorAttachment> colorAttachments {};
|
||||
};
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -211,10 +211,6 @@ uint32_t RenderTargetDump::hash() const {
|
||||
return mInternal->hash();
|
||||
}
|
||||
|
||||
const std::vector<unsigned char>& RenderTargetDump::bytes() const {
|
||||
return mInternal->bytes;
|
||||
}
|
||||
|
||||
bool RenderTargetDump::bytesFilled() const {
|
||||
return mInternal->bytesFilled;
|
||||
}
|
||||
|
||||
@@ -85,12 +85,6 @@ public:
|
||||
* @return The hash of the stored bytes.
|
||||
*/
|
||||
uint32_t hash() const;
|
||||
/**
|
||||
* Gets the bytes of the render target. The hash should usually be preferable for comparisons
|
||||
* but this is available for debugging.
|
||||
* @return The stored bytes.
|
||||
*/
|
||||
const std::vector<unsigned char>& bytes() const;
|
||||
/**
|
||||
* Thread safe as this is backed by an atomic.
|
||||
* Once this returns true it will never return false.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "ShaderGenerator.h"
|
||||
|
||||
#include <GlslangToSpv.h>
|
||||
#include <SPVRemapper.h>
|
||||
|
||||
#include <spirv_glsl.hpp>
|
||||
#include <spirv_msl.hpp>
|
||||
|
||||
@@ -184,7 +184,7 @@ std::vector<UniformConfig> GetUniformConfig(ShaderUniformType type) {
|
||||
"backend_test", "test_tex", 0,
|
||||
SamplerType::SAMPLER_2D, SamplerFormat::FLOAT, Precision::HIGH, false };
|
||||
return {{
|
||||
"test_tex", DescriptorType::SAMPLER, samplerInfo
|
||||
"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
|
||||
}};
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -32,24 +32,13 @@ do {
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define NONFATAL_FAIL_IF(skipEnvironment, rationale) \
|
||||
do { \
|
||||
SkipEnvironment skip(skipEnvironment); \
|
||||
if (skip.matches()) { \
|
||||
ADD_FAILURE() \
|
||||
<< "Failing test as the " << skip.describe() << "\n" \
|
||||
<< " This test has a known failure where " \
|
||||
<< rationale; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define FAIL_IF(skipEnvironment, rationale) \
|
||||
do { \
|
||||
SkipEnvironment skip(skipEnvironment); \
|
||||
if (skip.matches()) { \
|
||||
GTEST_FAIL() \
|
||||
<< "Failing test as the " << skip.describe() << "\n" \
|
||||
<< " This test should be able to succeed but it needs to fail early because " \
|
||||
<< " This test should be able to succeed but it needs to fail early because" \
|
||||
<< rationale; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
@@ -116,23 +116,13 @@ if __name__ == "__main__":
|
||||
'Remember to sync CMake after running this to '
|
||||
'move the new expected images to the binary '
|
||||
'directory.')
|
||||
parser.add_argument('-r', '--results_path',
|
||||
help='The path with the generated images directory, which should be where '
|
||||
'the test binary was run.')
|
||||
parser.add_argument('-s', '--source_expected_path', default="./expected_images",
|
||||
help='The directory that updated expected images should be written to, '
|
||||
'which should be the source directory copy.')
|
||||
parser.add_argument('-r', '--results_path')
|
||||
parser.add_argument('-s', '--source_expected_path', default="./expected_images")
|
||||
# The mutually exclusive options for how to process the actual images
|
||||
parser.add_argument('-b', '--batch', action='extend', nargs='*',
|
||||
help='If true copy all actual images to the source expected image '
|
||||
'directory.')
|
||||
parser.add_argument('-a', '--all', action='store_true',
|
||||
help='If true, visually compare all generated images.')
|
||||
parser.add_argument('-t', '--tests', action='store_true',
|
||||
help='If true use a test_detail.xml file that exists in the results_path '
|
||||
'directory to visually compare all images that failed a test.')
|
||||
parser.add_argument('-c', '--compare', action='extend', nargs='*',
|
||||
help='A list of image names to visually compare (without the .png suffix).')
|
||||
parser.add_argument('-b', '--batch', action='extend', nargs='*')
|
||||
parser.add_argument('-a', '--all', action='store_true')
|
||||
parser.add_argument('-t', '--tests', action='store_true')
|
||||
parser.add_argument('-c', '--compare', action='extend', nargs='*')
|
||||
|
||||
args = parser.parse_args()
|
||||
if not args.results_path:
|
||||
|
||||
@@ -260,8 +260,6 @@ TEST_F(BlitTest, ColorMinify) {
|
||||
}
|
||||
|
||||
TEST_F(BlitTest, ColorResolve) {
|
||||
NONFATAL_FAIL_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"Nothing is drawn, see b/417229577");
|
||||
auto& api = getDriverApi();
|
||||
|
||||
constexpr int kSrcTexWidth = 256;
|
||||
@@ -492,7 +490,7 @@ TEST_F(BlitTest, BlitRegion) {
|
||||
}
|
||||
|
||||
TEST_F(BlitTest, BlitRegionToSwapChain) {
|
||||
FAIL_IF(Backend::VULKAN, "Crashes due to not finding color attachment, see b/417481493");
|
||||
FAIL_IF(Backend::VULKAN, "Crashes due to not finding color attachment");
|
||||
auto& api = getDriverApi();
|
||||
mCleanup.addPostCall([&]() { executeCommands(); });
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Lifetimes.h"
|
||||
#include "Shader.h"
|
||||
#include "SharedShaders.h"
|
||||
#include "Skip.h"
|
||||
#include "TrianglePrimitive.h"
|
||||
|
||||
namespace test {
|
||||
@@ -160,8 +159,6 @@ TEST_F(BufferUpdatesTest, VertexBufferUpdate) {
|
||||
// This test renders two triangles in two separate draw calls. Between the draw calls, a uniform
|
||||
// buffer object is partially updated.
|
||||
TEST_F(BufferUpdatesTest, BufferObjectUpdateWithOffset) {
|
||||
NONFATAL_FAIL_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"All values including alpha are written as 0, see b/417254943");
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(api);
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace test {
|
||||
|
||||
TEST_F(BackendTest, FrameScheduledCallback) {
|
||||
SKIP_IF(Backend::OPENGL, "Frame callbacks are unsupported in OpenGL");
|
||||
SKIP_IF(Backend::VULKAN, "Frame callbacks are unsupported in Vulkan, see b/417254479");
|
||||
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(api);
|
||||
@@ -86,7 +85,6 @@ TEST_F(BackendTest, FrameScheduledCallback) {
|
||||
|
||||
TEST_F(BackendTest, FrameCompletedCallback) {
|
||||
SKIP_IF(Backend::OPENGL, "Frame callbacks are unsupported in OpenGL");
|
||||
SKIP_IF(Backend::VULKAN, "Frame callbacks are unsupported in Vulkan, see b/417254479");
|
||||
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(api);
|
||||
|
||||
@@ -99,8 +99,6 @@ struct MaterialParams {
|
||||
// The problems are caused by both uploading and rendering into the same texture, since the OpenGL
|
||||
// backend's readPixels does not work correctly with textures that have image data uploaded.
|
||||
TEST_F(BackendTest, FeedbackLoops) {
|
||||
NONFATAL_FAIL_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"Image is unexpectedly darker, see b/417226296");
|
||||
SKIP_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::OPENGL),
|
||||
"OpenGL image is upside down due to readPixels failing for texture with uploaded image "
|
||||
"data");
|
||||
@@ -120,7 +118,7 @@ TEST_F(BackendTest, FeedbackLoops) {
|
||||
Shader shader = Shader(api, cleanup, ShaderConfig {
|
||||
.vertexShader = fullscreenVs,
|
||||
.fragmentShader = fullscreenFs,
|
||||
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}, {"Params"}}
|
||||
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}, {"Params"}}
|
||||
});
|
||||
|
||||
TrianglePrimitive const triangle(getDriverApi());
|
||||
|
||||
@@ -212,7 +212,7 @@ static SamplerFormat getSamplerFormat(TextureFormat textureFormat) {
|
||||
}
|
||||
|
||||
TEST_F(LoadImageTest, UpdateImage2D) {
|
||||
FAIL_IF(Backend::VULKAN, "Multiple test cases crash, see b/417481434");
|
||||
FAIL_IF(Backend::VULKAN, "Multiple test cases crash");
|
||||
|
||||
// All of these test cases should result in the same rendered image, and thus the same hash.
|
||||
static const uint32_t expectedHash = 3644679986;
|
||||
@@ -308,7 +308,7 @@ TEST_F(LoadImageTest, UpdateImage2D) {
|
||||
Shader shader(api, cleanup, ShaderConfig{
|
||||
.vertexShader = mVertexShader,
|
||||
.fragmentShader= fragment,
|
||||
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
|
||||
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}}
|
||||
});
|
||||
|
||||
// Create a Texture.
|
||||
@@ -372,7 +372,7 @@ TEST_F(LoadImageTest, UpdateImageSRGB) {
|
||||
getSamplerTypeName(textureFormat), fragmentTemplate);
|
||||
Shader shader(api, cleanup, ShaderConfig{
|
||||
.vertexShader = mVertexShader, .fragmentShader = fragment, .uniforms = {{
|
||||
"test_tex", DescriptorType::SAMPLER, samplerInfo
|
||||
"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
|
||||
}}});
|
||||
|
||||
// Create a texture.
|
||||
@@ -447,7 +447,7 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) {
|
||||
Shader shader(api, cleanup, ShaderConfig {
|
||||
.vertexShader = mVertexShader,
|
||||
.fragmentShader = fragment,
|
||||
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
|
||||
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}}
|
||||
});
|
||||
|
||||
// Create a texture with 3 mip levels.
|
||||
@@ -485,9 +485,6 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) {
|
||||
}
|
||||
|
||||
TEST_F(LoadImageTest, UpdateImage3D) {
|
||||
NONFATAL_FAIL_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"Checkerboard not drawn, possibly due to using wrong z value of 3d texture, "
|
||||
"see b/417254499");
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(api);
|
||||
api.startCapture();
|
||||
@@ -511,7 +508,7 @@ TEST_F(LoadImageTest, UpdateImage3D) {
|
||||
Shader shader(api, cleanup, ShaderConfig {
|
||||
.vertexShader = mVertexShader,
|
||||
.fragmentShader = fragment,
|
||||
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
|
||||
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_ARRAY_FLOAT, samplerInfo}}
|
||||
});
|
||||
|
||||
// Create a texture.
|
||||
|
||||
@@ -82,7 +82,7 @@ TEST_F(BackendTest, TextureViewLod) {
|
||||
.vertexShader = vertexShader,
|
||||
.fragmentShader = fragmentTexturedLod,
|
||||
.uniforms = {{
|
||||
"backend_test_sib_tex", DescriptorType::SAMPLER, samplerInfo
|
||||
"backend_test_sib_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
|
||||
}}
|
||||
});
|
||||
|
||||
|
||||
@@ -81,8 +81,7 @@ void main() {
|
||||
|
||||
TEST_F(BackendTest, PushConstants) {
|
||||
SKIP_IF(Backend::OPENGL, "Push constants not supported on OpenGL");
|
||||
FAIL_IF(Backend::VULKAN,
|
||||
"Crashing due to no program set when setting push constants, see b/417477740");
|
||||
FAIL_IF(Backend::VULKAN, "Crashing due to no program set when setting push constants");
|
||||
|
||||
auto& api = getDriverApi();
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Lifetimes.h"
|
||||
#include "Shader.h"
|
||||
#include "SharedShaders.h"
|
||||
#include "Skip.h"
|
||||
#include "TrianglePrimitive.h"
|
||||
|
||||
#include <utils/Hash.h>
|
||||
@@ -75,8 +74,6 @@ public:
|
||||
};
|
||||
|
||||
TEST_F(ReadPixelsTest, ReadPixels) {
|
||||
NONFATAL_FAIL_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"Two cases fail, see b/417255941 and b/417255943");
|
||||
// These test scenarios use a known hash of the result pixel buffer to decide pass / fail,
|
||||
// asserting an exact pixel-for-pixel match. So far, rendering on macOS and iPhone have had
|
||||
// deterministic results. Take this test with a grain of salt, however, as other platform / GPU
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Lifetimes.h"
|
||||
#include "Shader.h"
|
||||
#include "SharedShaders.h"
|
||||
#include "Skip.h"
|
||||
#include "TrianglePrimitive.h"
|
||||
|
||||
#include <utils/Hash.h>
|
||||
@@ -31,8 +30,6 @@ using namespace filament;
|
||||
using namespace filament::backend;
|
||||
|
||||
TEST_F(BackendTest, ScissorViewportRegion) {
|
||||
NONFATAL_FAIL_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"Affected area in wrong corner, see b/417229118");
|
||||
auto& api = getDriverApi();
|
||||
|
||||
constexpr int kSrcTexWidth = 1024;
|
||||
|
||||
@@ -117,8 +117,6 @@ public:
|
||||
};
|
||||
|
||||
TEST_F(BasicStencilBufferTest, StencilBuffer) {
|
||||
SKIP_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"Stencil not supported, see b/417230776");
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(api);
|
||||
|
||||
@@ -141,8 +139,6 @@ TEST_F(BasicStencilBufferTest, StencilBuffer) {
|
||||
}
|
||||
|
||||
TEST_F(BasicStencilBufferTest, DepthAndStencilBuffer) {
|
||||
SKIP_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"Stencil not supported, see b/417230776");
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(api);
|
||||
|
||||
@@ -166,8 +162,6 @@ TEST_F(BasicStencilBufferTest, DepthAndStencilBuffer) {
|
||||
}
|
||||
|
||||
TEST_F(BasicStencilBufferTest, StencilBufferMSAA) {
|
||||
SKIP_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"Stencil not supported, see b/417230776");
|
||||
SKIP_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::OPENGL), "Stencil isn't applied");
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(api);
|
||||
|
||||
@@ -21,13 +21,17 @@
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <filament/ToneMapper.h>
|
||||
#include <filament/ColorSpace.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <memory>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -201,15 +205,14 @@ public:
|
||||
*
|
||||
* The default tone mapping operator is ACESLegacyToneMapper.
|
||||
*
|
||||
* The specified tone mapper must have a lifecycle that exceeds the lifetime of
|
||||
* this builder. Since the build(Engine&) method is synchronous, it is safe to
|
||||
* delete the tone mapper object after that finishes executing.
|
||||
* The ownership of the specified tone mapper is shared with the builder and built
|
||||
* ColorGrading object.
|
||||
*
|
||||
* @param toneMapper The tone mapping operator to apply to the HDR color buffer
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& toneMapper(ToneMapper const* UTILS_NULLABLE toneMapper) noexcept;
|
||||
Builder& toneMapper(std::shared_ptr<ToneMapper> toneMapper) noexcept;
|
||||
|
||||
/**
|
||||
* Selects the tone mapping operator to apply to the HDR color buffer as the last
|
||||
@@ -487,7 +490,118 @@ public:
|
||||
friend class FColorGrading;
|
||||
};
|
||||
|
||||
protected:
|
||||
/** Returns the quality level used to create this ColorGrading object. */
|
||||
QualityLevel getQuality() const noexcept;
|
||||
|
||||
/** Returns the LUT format used to create this ColorGrading object. */
|
||||
LutFormat getLutFormat() const noexcept;
|
||||
|
||||
/** Returns the LUT dimensions used to create this ColorGrading object. */
|
||||
uint8_t getLutDimensions() const noexcept;
|
||||
|
||||
/** Returns the tone mapper used to create this ColorGrading object. */
|
||||
const ToneMapper& getToneMapper() const noexcept;
|
||||
|
||||
/** Returns whether luminance scaling was enabled during creation. */
|
||||
bool isLuminanceScalingEnabled() const noexcept;
|
||||
|
||||
/** Returns whether gamut mapping was enabled during creation. */
|
||||
bool isGamutMappingEnabled() const noexcept;
|
||||
|
||||
/** Returns the exposure value used to create this ColorGrading object. */
|
||||
float getExposure() const noexcept;
|
||||
|
||||
/** Returns the night adaptation value used to create this ColorGrading object. */
|
||||
float getNightAdaptation() const noexcept;
|
||||
|
||||
/** Returns the white balance temperature used to create this ColorGrading object. */
|
||||
float getWhiteBalanceTemperature() const noexcept;
|
||||
|
||||
/** Returns the white balance tint used to create this ColorGrading object. */
|
||||
float getWhiteBalanceTint() const noexcept;
|
||||
|
||||
/** Returns the channel mixer output for the red channel. */
|
||||
math::float3 getChannelMixerOutRed() const noexcept;
|
||||
|
||||
/** Returns the channel mixer output for the green channel. */
|
||||
math::float3 getChannelMixerOutGreen() const noexcept;
|
||||
|
||||
/** Returns the channel mixer output for the blue channel. */
|
||||
math::float3 getChannelMixerOutBlue() const noexcept;
|
||||
|
||||
/** Returns the shadows adjustment used to create this ColorGrading object. */
|
||||
math::float3 getShadows() const noexcept;
|
||||
|
||||
/** Returns the midtones adjustment used to create this ColorGrading object. */
|
||||
math::float3 getMidtones() const noexcept;
|
||||
|
||||
/** Returns the highlights adjustment used to create this ColorGrading object. */
|
||||
math::float3 getHighlights() const noexcept;
|
||||
|
||||
/** Returns the shadow/midtones/highlights ranges used to create this ColorGrading object. */
|
||||
math::float4 getShadowMidtonesHighlightsRanges() const noexcept;
|
||||
|
||||
/** Returns the slope adjustment used to create this ColorGrading object. */
|
||||
math::float3 getSlope() const noexcept;
|
||||
|
||||
/** Returns the offset adjustment used to create this ColorGrading object. */
|
||||
math::float3 getOffset() const noexcept;
|
||||
|
||||
/** Returns the power adjustment used to create this ColorGrading object. */
|
||||
math::float3 getPower() const noexcept;
|
||||
|
||||
/** Returns the contrast value used to create this ColorGrading object. */
|
||||
float getContrast() const noexcept;
|
||||
|
||||
/** Returns the vibrance value used to create this ColorGrading object. */
|
||||
float getVibrance() const noexcept;
|
||||
|
||||
/** Returns the saturation value used to create this ColorGrading object. */
|
||||
float getSaturation() const noexcept;
|
||||
|
||||
/** Returns the shadow gamma curve adjustment used to create this ColorGrading object. */
|
||||
math::float3 getCurvesShadowGamma() const noexcept;
|
||||
|
||||
/** Returns the mid-point curve adjustment used to create this ColorGrading object. */
|
||||
math::float3 getCurvesMidPoint() const noexcept;
|
||||
|
||||
/** Returns the highlight scale curve adjustment used to create this ColorGrading object. */
|
||||
math::float3 getCurvesHighlightScale() const noexcept;
|
||||
|
||||
/** Returns the output color space used to create this ColorGrading object. */
|
||||
const color::ColorSpace& getOutputColorSpace() const noexcept;
|
||||
|
||||
protected :
|
||||
struct Settings {
|
||||
LutFormat lutFormat = LutFormat::INTEGER;
|
||||
uint8_t lutDimensions = 32;
|
||||
std::shared_ptr<ToneMapper> toneMapper = std::make_shared<ACESLegacyToneMapper>();
|
||||
bool luminanceScaling = false;
|
||||
bool gummapMapping = false;
|
||||
float exposure = 0.0f;
|
||||
float nightAdaptation = 0.0f;
|
||||
float whiteBalanceTemperature = 0.0f;
|
||||
float whiteBalanceTint = 0.0f;
|
||||
math::float3 channelMixerOutRed{1.0f, 0.0f, 0.0f};
|
||||
math::float3 channelMixerOutGreen{0.0f, 1.0f, 0.0f};
|
||||
math::float3 channelMixerOutBlue{0.0f, 0.0f, 1.0f};
|
||||
math::float3 shadows{1.0f, 1.0f, 1.0f};
|
||||
math::float3 midtones{1.0f, 1.0f, 1.0f};
|
||||
math::float3 highlights{1.0f, 1.0f, 1.0f};
|
||||
math::float4 ShadowMidtonesHighlightsRanges{0.0f, 0.333f, 0.55f, 1.0f};
|
||||
math::float3 slope{1.0f};
|
||||
math::float3 offset{0.0f};
|
||||
math::float3 power{1.0f};
|
||||
float contrast = 1.0f;
|
||||
float vibrance = 1.0f;
|
||||
float saturation = 1.0f;
|
||||
math::float3 curvesShadowGamma{1.0f, 1.0f, 1.0f};
|
||||
math::float3 curvesMidPoint{1.0f, 1.0f, 1.0f};
|
||||
math::float3 curvesHighlightScale{1.0f, 1.0f, 1.0f};
|
||||
color::ColorSpace colorSpace = color::Rec709 - color::sRGB - color::D65;
|
||||
};
|
||||
Settings mSettings;
|
||||
|
||||
// prevent heap allocation
|
||||
~ColorGrading() = default;
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <backend/CallbackHandler.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/PresentCallable.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Invocable.h>
|
||||
@@ -34,7 +35,7 @@ class Engine;
|
||||
/**
|
||||
* A swap chain represents an Operating System's *native* renderable surface.
|
||||
*
|
||||
* Typically, it's a native window or a view. Because a SwapChain is initialized from a
|
||||
* Typically it's a native window or a view. Because a SwapChain is initialized from a
|
||||
* native object, it is given to filament as a `void *`, which must be of the proper type
|
||||
* for each platform filament is running on.
|
||||
*
|
||||
@@ -157,7 +158,7 @@ public:
|
||||
/**
|
||||
* Requests a SwapChain with an alpha channel.
|
||||
*/
|
||||
static constexpr uint64_t CONFIG_TRANSPARENT = backend::SWAP_CHAIN_CONFIG_TRANSPARENT;
|
||||
static const uint64_t CONFIG_TRANSPARENT = backend::SWAP_CHAIN_CONFIG_TRANSPARENT;
|
||||
|
||||
/**
|
||||
* This flag indicates that the swap chain may be used as a source surface
|
||||
@@ -167,13 +168,13 @@ public:
|
||||
* @see
|
||||
* Renderer.copyFrame()
|
||||
*/
|
||||
static constexpr uint64_t CONFIG_READABLE = backend::SWAP_CHAIN_CONFIG_READABLE;
|
||||
static const uint64_t CONFIG_READABLE = backend::SWAP_CHAIN_CONFIG_READABLE;
|
||||
|
||||
/**
|
||||
* Indicates that the native X11 window is an XCB window rather than an XLIB window.
|
||||
* This is ignored on non-Linux platforms and in builds that support only one X11 API.
|
||||
*/
|
||||
static constexpr uint64_t CONFIG_ENABLE_XCB = backend::SWAP_CHAIN_CONFIG_ENABLE_XCB;
|
||||
static const uint64_t CONFIG_ENABLE_XCB = backend::SWAP_CHAIN_CONFIG_ENABLE_XCB;
|
||||
|
||||
/**
|
||||
* Indicates that the native window is a CVPixelBufferRef.
|
||||
@@ -185,7 +186,7 @@ public:
|
||||
* Filament. Filament will call CVPixelBufferRetain during Engine::createSwapChain, and
|
||||
* CVPixelBufferRelease when the swap chain is destroyed.
|
||||
*/
|
||||
static constexpr uint64_t CONFIG_APPLE_CVPIXELBUFFER =
|
||||
static const uint64_t CONFIG_APPLE_CVPIXELBUFFER =
|
||||
backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER;
|
||||
|
||||
/**
|
||||
@@ -302,7 +303,6 @@ public:
|
||||
*
|
||||
* @param handler Handler to dispatch the callback or nullptr for the default handler.
|
||||
* @param callback Callback called when the frame is scheduled.
|
||||
* @param flags
|
||||
*
|
||||
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
|
||||
* backends ignore the callback (which will never be called) and proceed normally.
|
||||
@@ -314,7 +314,7 @@ public:
|
||||
FrameScheduledCallback&& callback = {}, uint64_t flags = 0);
|
||||
|
||||
/**
|
||||
* Returns whether this SwapChain currently has a FrameScheduledCallback set.
|
||||
* Returns whether or not this SwapChain currently has a FrameScheduledCallback set.
|
||||
*
|
||||
* @return true, if the last call to setFrameScheduledCallback set a callback
|
||||
*
|
||||
|
||||
@@ -54,6 +54,8 @@ namespace filament {
|
||||
struct UTILS_PUBLIC ToneMapper {
|
||||
ToneMapper() noexcept;
|
||||
virtual ~ToneMapper() noexcept;
|
||||
ToneMapper(ToneMapper const&) noexcept;
|
||||
ToneMapper& operator=(ToneMapper const&) noexcept = default;
|
||||
|
||||
/**
|
||||
* Maps an open domain (or "scene referred" values) color value to display
|
||||
@@ -69,6 +71,13 @@ struct UTILS_PUBLIC ToneMapper {
|
||||
*/
|
||||
virtual math::float3 operator()(math::float3 c) const noexcept = 0;
|
||||
|
||||
/**
|
||||
* Creates a copy of this tone mapper instance.
|
||||
*
|
||||
* @return A pointer to a new ToneMapper instance that is a copy of this instance.
|
||||
*/
|
||||
virtual ToneMapper* clone() const noexcept = 0;
|
||||
|
||||
/**
|
||||
* If true, then this function holds that f(x) = vec3(f(x.r), f(x.g), f(x.b))
|
||||
*
|
||||
@@ -92,8 +101,10 @@ struct UTILS_PUBLIC ToneMapper {
|
||||
struct UTILS_PUBLIC LinearToneMapper final : public ToneMapper {
|
||||
LinearToneMapper() noexcept;
|
||||
~LinearToneMapper() noexcept final;
|
||||
LinearToneMapper(LinearToneMapper const&) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 c) const noexcept override;
|
||||
LinearToneMapper* clone() const noexcept override;
|
||||
bool isOneDimensional() const noexcept override { return true; }
|
||||
bool isLDR() const noexcept override { return true; }
|
||||
};
|
||||
@@ -106,8 +117,10 @@ struct UTILS_PUBLIC LinearToneMapper final : public ToneMapper {
|
||||
struct UTILS_PUBLIC ACESToneMapper final : public ToneMapper {
|
||||
ACESToneMapper() noexcept;
|
||||
~ACESToneMapper() noexcept final;
|
||||
ACESToneMapper(ACESToneMapper const&) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 c) const noexcept override;
|
||||
ACESToneMapper* clone() const noexcept override;
|
||||
bool isOneDimensional() const noexcept override { return false; }
|
||||
bool isLDR() const noexcept override { return false; }
|
||||
};
|
||||
@@ -121,8 +134,10 @@ struct UTILS_PUBLIC ACESToneMapper final : public ToneMapper {
|
||||
struct UTILS_PUBLIC ACESLegacyToneMapper final : public ToneMapper {
|
||||
ACESLegacyToneMapper() noexcept;
|
||||
~ACESLegacyToneMapper() noexcept final;
|
||||
ACESLegacyToneMapper(ACESLegacyToneMapper const&) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 c) const noexcept override;
|
||||
ACESLegacyToneMapper* clone() const noexcept override;
|
||||
bool isOneDimensional() const noexcept override { return false; }
|
||||
bool isLDR() const noexcept override { return false; }
|
||||
};
|
||||
@@ -136,8 +151,10 @@ struct UTILS_PUBLIC ACESLegacyToneMapper final : public ToneMapper {
|
||||
struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
|
||||
FilmicToneMapper() noexcept;
|
||||
~FilmicToneMapper() noexcept final;
|
||||
FilmicToneMapper(FilmicToneMapper const&) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 x) const noexcept override;
|
||||
FilmicToneMapper* clone() const noexcept override;
|
||||
bool isOneDimensional() const noexcept override { return true; }
|
||||
bool isLDR() const noexcept override { return false; }
|
||||
};
|
||||
@@ -150,8 +167,10 @@ struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
|
||||
struct UTILS_PUBLIC PBRNeutralToneMapper final : public ToneMapper {
|
||||
PBRNeutralToneMapper() noexcept;
|
||||
~PBRNeutralToneMapper() noexcept final;
|
||||
PBRNeutralToneMapper(PBRNeutralToneMapper const&) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 x) const noexcept override;
|
||||
virtual PBRNeutralToneMapper* clone() const noexcept override;
|
||||
bool isOneDimensional() const noexcept override { return false; }
|
||||
bool isLDR() const noexcept override { return false; }
|
||||
};
|
||||
@@ -173,8 +192,10 @@ struct UTILS_PUBLIC AgxToneMapper final : public ToneMapper {
|
||||
*/
|
||||
explicit AgxToneMapper(AgxLook look = AgxLook::NONE) noexcept;
|
||||
~AgxToneMapper() noexcept final;
|
||||
AgxToneMapper(AgxToneMapper const&) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 x) const noexcept override;
|
||||
virtual AgxToneMapper* clone() const noexcept override;
|
||||
bool isOneDimensional() const noexcept override { return false; }
|
||||
bool isLDR() const noexcept override { return false; }
|
||||
|
||||
@@ -215,12 +236,13 @@ struct UTILS_PUBLIC GenericToneMapper final : public ToneMapper {
|
||||
) noexcept;
|
||||
~GenericToneMapper() noexcept final;
|
||||
|
||||
GenericToneMapper(GenericToneMapper const&) = delete;
|
||||
GenericToneMapper& operator=(GenericToneMapper const&) = delete;
|
||||
GenericToneMapper(GenericToneMapper const& rhs) noexcept;
|
||||
GenericToneMapper& operator=(GenericToneMapper const& rhs) noexcept;
|
||||
GenericToneMapper(GenericToneMapper&& rhs) noexcept;
|
||||
GenericToneMapper& operator=(GenericToneMapper&& rhs) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 x) const noexcept override;
|
||||
GenericToneMapper* clone() const noexcept override;
|
||||
bool isOneDimensional() const noexcept override { return true; }
|
||||
bool isLDR() const noexcept override { return false; }
|
||||
|
||||
@@ -283,8 +305,10 @@ private:
|
||||
struct UTILS_PUBLIC DisplayRangeToneMapper final : public ToneMapper {
|
||||
DisplayRangeToneMapper() noexcept;
|
||||
~DisplayRangeToneMapper() noexcept override;
|
||||
DisplayRangeToneMapper(DisplayRangeToneMapper const&) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 c) const noexcept override;
|
||||
DisplayRangeToneMapper* clone() const noexcept override;
|
||||
bool isOneDimensional() const noexcept override { return false; }
|
||||
bool isLDR() const noexcept override { return false; }
|
||||
};
|
||||
|
||||
@@ -16,22 +16,13 @@
|
||||
|
||||
#include "AtlasAllocator.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/QuadTree.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
using namespace utils;
|
||||
|
||||
static constexpr std::pair<uint8_t, uint8_t> unmorton(uint16_t const m) noexcept {
|
||||
static inline constexpr std::pair<uint8_t, uint8_t> unmorton(uint16_t const m) noexcept {
|
||||
uint32_t r = (m | (uint32_t(m) << 15u)) & 0x55555555u;
|
||||
r = (r | (r >> 1u)) & 0x33333333u;
|
||||
r = (r | (r >> 2u)) & 0x0f0f0f0fu;
|
||||
@@ -174,8 +165,8 @@ AtlasAllocator::NodeId AtlasAllocator::allocateInLayer(size_t const maxHeight) n
|
||||
NodeId found{ -1, 0 };
|
||||
QuadTree::traverse(candidate.l, candidate.code,
|
||||
[this, n, &found](NodeId const& curr) -> QuadTree::TraversalResult {
|
||||
size_t const j = index(curr.l, curr.code);
|
||||
Node& node = mQuadTree[j];
|
||||
size_t const i = index(curr.l, curr.code);
|
||||
Node& node = mQuadTree[i];
|
||||
if (curr.l == n) {
|
||||
found = curr;
|
||||
assert_invariant(!node.hasChildren());
|
||||
|
||||
@@ -232,7 +232,7 @@ PostProcessManager::~PostProcessManager() noexcept = default;
|
||||
void PostProcessManager::setFrameUniforms(DriverApi& driver,
|
||||
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
|
||||
mPostProcessDescriptorSet.setFrameUniforms(driver, uniforms);
|
||||
mSsrPassDescriptorSet.setFrameUniforms(uniforms);
|
||||
mSsrPassDescriptorSet.setFrameUniforms(mEngine, uniforms);
|
||||
}
|
||||
|
||||
void PostProcessManager::bindPostProcessDescriptorSet(DriverApi& driver) const noexcept {
|
||||
@@ -504,6 +504,7 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph
|
||||
FrameGraphTexture::Usage::DEPTH_ATTACHMENT);
|
||||
|
||||
if (config.picking) {
|
||||
// FIXME: the DescriptorSetLayout must specify SAMPLER_FLOAT
|
||||
data.picking = builder.createTexture("Picking Buffer", {
|
||||
.width = width, .height = height,
|
||||
.format = isES2 ? TextureFormat::RGBA8 : TextureFormat::RG32F });
|
||||
@@ -653,7 +654,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::ssr(FrameGraph& fg,
|
||||
options, passBuilder = passBuilder]
|
||||
(FrameGraphResources const& resources, auto const& data, DriverApi& driver) mutable {
|
||||
// set structure sampler
|
||||
mSsrPassDescriptorSet.prepareStructure(data.structure ?
|
||||
mSsrPassDescriptorSet.prepareStructure(mEngine, data.structure ?
|
||||
resources.getTexture(data.structure) : getOneTexture());
|
||||
|
||||
// set screen-space reflections and screen-space refractions
|
||||
@@ -664,7 +665,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::ssr(FrameGraph& fg,
|
||||
// the history sampler is a regular texture2D
|
||||
TextureHandle const history = data.history ?
|
||||
resources.getTexture(data.history) : getZeroTexture();
|
||||
mSsrPassDescriptorSet.prepareHistorySSR(history, reprojection, uvFromViewMatrix, options);
|
||||
mSsrPassDescriptorSet.prepareHistorySSR(mEngine, history, reprojection, uvFromViewMatrix, options);
|
||||
|
||||
mSsrPassDescriptorSet.commit(mEngine);
|
||||
|
||||
|
||||
@@ -921,7 +921,6 @@ backend::Viewport RenderPass::Executor::applyScissorViewport(
|
||||
UTILS_NOINLINE // no need to be inlined
|
||||
void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
|
||||
Command const* first, Command const* last) const noexcept {
|
||||
|
||||
SYSTRACE_CALL();
|
||||
SYSTRACE_CONTEXT();
|
||||
|
||||
@@ -942,6 +941,13 @@ void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
|
||||
driver.scissor(mScissor);
|
||||
}
|
||||
|
||||
// If we have a mColorPassDescriptorSet, we need to use its idea of "VSM" to select
|
||||
// the descriptor set layout. Materials always offer both.
|
||||
// If we don't have a mColorPassDescriptorSet, it doesn't matter because the layout
|
||||
// are chosen via the variant only.
|
||||
bool const useVsmDescriptorSetLayout =
|
||||
mColorPassDescriptorSet ? mColorPassDescriptorSet->isVSM() : false;
|
||||
|
||||
bool const polygonOffsetOverride = mPolygonOffsetOverride;
|
||||
PipelineState pipeline{
|
||||
// initialize with polygon offset override
|
||||
@@ -1051,8 +1057,13 @@ void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
|
||||
|
||||
// Each material has its own version of the per-view descriptor-set layout,
|
||||
// because it depends on the material features (e.g. lit/unlit)
|
||||
// TODO: QUESTION: are
|
||||
// Variant::isValidDepthVariant(info.materialVariant) and
|
||||
// Variant::isSSRVariant(info.materialVariant)
|
||||
// constant? If so we could precompute ma->getPerViewDescriptorSetLayout()
|
||||
pipeline.pipelineLayout.setLayout[+DescriptorSetBindingPoints::PER_VIEW] =
|
||||
ma->getPerViewDescriptorSetLayout(info.materialVariant).getHandle();
|
||||
ma->getPerViewDescriptorSetLayout(info.materialVariant,
|
||||
useVsmDescriptorSetLayout).getHandle();
|
||||
|
||||
// Each material has a per-material descriptor-set layout which encodes the
|
||||
// material's parameters (ubo and samplers)
|
||||
|
||||
@@ -205,11 +205,13 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass(
|
||||
view.prepareSSAO(data.ssao ?
|
||||
resources.getTexture(data.ssao) : engine.getOneTextureArray());
|
||||
|
||||
view.prepareShadowMapping(view.getVsmShadowOptions().highPrecision);
|
||||
view.prepareShadowMapping(engine, view.getVsmShadowOptions().highPrecision);
|
||||
|
||||
// set shadow sampler
|
||||
view.prepareShadow(data.shadows ?
|
||||
resources.getTexture(data.shadows) : engine.getOneTextureArray());
|
||||
resources.getTexture(data.shadows) :
|
||||
(view.getShadowType() != ShadowType::PCF ?
|
||||
engine.getOneTextureArray() : engine.getOneTextureArrayDepth()));
|
||||
|
||||
// set structure sampler
|
||||
view.prepareStructure(data.structure ?
|
||||
|
||||
@@ -188,7 +188,8 @@ float3 ACES(float3 color, float brightness) noexcept {
|
||||
|
||||
#define DEFAULT_CONSTRUCTORS(A) \
|
||||
A::A() noexcept = default; \
|
||||
A::~A() noexcept = default;
|
||||
A::~A() noexcept = default; \
|
||||
A::A(A const&) noexcept = default;
|
||||
|
||||
DEFAULT_CONSTRUCTORS(ToneMapper)
|
||||
|
||||
@@ -202,6 +203,10 @@ float3 LinearToneMapper::operator()(float3 const v) const noexcept {
|
||||
return saturate(v);
|
||||
}
|
||||
|
||||
LinearToneMapper* LinearToneMapper::clone() const noexcept {
|
||||
return new LinearToneMapper(*this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// ACES tone mappers
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -212,12 +217,20 @@ float3 ACESToneMapper::operator()(float3 const c) const noexcept {
|
||||
return aces::ACES(c, 1.0f);
|
||||
}
|
||||
|
||||
ACESToneMapper* ACESToneMapper::clone() const noexcept {
|
||||
return new ACESToneMapper(*this);
|
||||
}
|
||||
|
||||
DEFAULT_CONSTRUCTORS(ACESLegacyToneMapper)
|
||||
|
||||
float3 ACESLegacyToneMapper::operator()(float3 const c) const noexcept {
|
||||
return aces::ACES(c, 1.0f / 0.6f);
|
||||
}
|
||||
|
||||
ACESLegacyToneMapper* ACESLegacyToneMapper::clone() const noexcept {
|
||||
return new ACESLegacyToneMapper(*this);
|
||||
}
|
||||
|
||||
DEFAULT_CONSTRUCTORS(FilmicToneMapper)
|
||||
|
||||
float3 FilmicToneMapper::operator()(float3 const x) const noexcept {
|
||||
@@ -230,6 +243,10 @@ float3 FilmicToneMapper::operator()(float3 const x) const noexcept {
|
||||
return (x * (a * x + b)) / (x * (c * x + d) + e);
|
||||
}
|
||||
|
||||
FilmicToneMapper* FilmicToneMapper::clone() const noexcept {
|
||||
return new FilmicToneMapper(*this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// PBR Neutral tone mapper
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -256,12 +273,17 @@ float3 PBRNeutralToneMapper::operator()(float3 color) const noexcept {
|
||||
return mix(color, float3(newPeak), g);
|
||||
}
|
||||
|
||||
PBRNeutralToneMapper* PBRNeutralToneMapper::clone() const noexcept {
|
||||
return new PBRNeutralToneMapper(*this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// AgX tone mapper
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
AgxToneMapper::AgxToneMapper(AgxLook const look) noexcept : look(look) {}
|
||||
AgxToneMapper::~AgxToneMapper() noexcept = default;
|
||||
AgxToneMapper::AgxToneMapper(AgxToneMapper const& rhs) noexcept = default;
|
||||
|
||||
// These matrices taken from Blender's implementation of AgX, which works with Rec.2020 primaries.
|
||||
// https://github.com/EaryChow/AgX_LUT_Gen/blob/main/AgXBaseRec2020.py
|
||||
@@ -356,6 +378,10 @@ float3 AgxToneMapper::operator()(float3 v) const noexcept {
|
||||
return v;
|
||||
}
|
||||
|
||||
AgxToneMapper* AgxToneMapper::clone() const noexcept {
|
||||
return new AgxToneMapper(*this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Display range tone mapper
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -394,6 +420,10 @@ float3 DisplayRangeToneMapper::operator()(float3 const c) const noexcept {
|
||||
return mix(debugColors[index], debugColors[index + 1], saturate(v - float(index)));
|
||||
}
|
||||
|
||||
DisplayRangeToneMapper* DisplayRangeToneMapper::clone() const noexcept {
|
||||
return new DisplayRangeToneMapper(*this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Generic tone mapper
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -454,7 +484,19 @@ GenericToneMapper::~GenericToneMapper() noexcept {
|
||||
delete mOptions;
|
||||
}
|
||||
|
||||
GenericToneMapper::GenericToneMapper(GenericToneMapper&& rhs) noexcept : mOptions(rhs.mOptions) {
|
||||
GenericToneMapper::GenericToneMapper(GenericToneMapper const& rhs) noexcept {
|
||||
mOptions = new Options(*rhs.mOptions);
|
||||
}
|
||||
|
||||
GenericToneMapper& GenericToneMapper::operator=(GenericToneMapper const& rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
delete mOptions;
|
||||
mOptions = new Options(*rhs.mOptions);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
GenericToneMapper::GenericToneMapper(GenericToneMapper&& rhs) noexcept : mOptions(rhs.mOptions) {
|
||||
rhs.mOptions = nullptr;
|
||||
}
|
||||
|
||||
@@ -469,6 +511,10 @@ float3 GenericToneMapper::operator()(float3 x) const noexcept {
|
||||
return mOptions->outputScale * x / (x + mOptions->inputScale);
|
||||
}
|
||||
|
||||
GenericToneMapper* GenericToneMapper::clone() const noexcept {
|
||||
return new GenericToneMapper(*this);
|
||||
}
|
||||
|
||||
float GenericToneMapper::getContrast() const noexcept { return mOptions->contrast; }
|
||||
float GenericToneMapper::getMidGrayIn() const noexcept { return mOptions->midGrayIn; }
|
||||
float GenericToneMapper::getMidGrayOut() const noexcept { return mOptions->midGrayOut; }
|
||||
|
||||
@@ -49,7 +49,7 @@ using namespace backend;
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct ColorGrading::BuilderDetails {
|
||||
const ToneMapper* toneMapper = nullptr;
|
||||
std::shared_ptr<ToneMapper> toneMapper = nullptr;
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
@@ -173,7 +173,7 @@ ColorGrading::Builder& ColorGrading::Builder::dimensions(uint8_t const dim) noex
|
||||
return *this;
|
||||
}
|
||||
|
||||
ColorGrading::Builder& ColorGrading::Builder::toneMapper(const ToneMapper* toneMapper) noexcept {
|
||||
ColorGrading::Builder& ColorGrading::Builder::toneMapper(std::shared_ptr<ToneMapper> toneMapper) noexcept {
|
||||
mImpl->toneMapper = toneMapper;
|
||||
return *this;
|
||||
}
|
||||
@@ -271,6 +271,110 @@ ColorGrading::Builder& ColorGrading::Builder::outputColorSpace(
|
||||
return *this;
|
||||
}
|
||||
|
||||
ColorGrading::LutFormat ColorGrading::getLutFormat() const noexcept {
|
||||
return mSettings.lutFormat;
|
||||
}
|
||||
|
||||
uint8_t ColorGrading::getLutDimensions() const noexcept {
|
||||
return mSettings.lutDimensions;
|
||||
}
|
||||
|
||||
const ToneMapper& ColorGrading::getToneMapper() const noexcept {
|
||||
return *mSettings.toneMapper;
|
||||
}
|
||||
|
||||
bool ColorGrading::isLuminanceScalingEnabled() const noexcept {
|
||||
return mSettings.luminanceScaling;
|
||||
}
|
||||
|
||||
bool ColorGrading::isGamutMappingEnabled() const noexcept {
|
||||
return mSettings.gummapMapping;
|
||||
}
|
||||
|
||||
float ColorGrading::getExposure() const noexcept {
|
||||
return mSettings.exposure;
|
||||
}
|
||||
|
||||
float ColorGrading::getNightAdaptation() const noexcept {
|
||||
return mSettings.nightAdaptation;
|
||||
}
|
||||
|
||||
float ColorGrading::getWhiteBalanceTemperature() const noexcept {
|
||||
return mSettings.whiteBalanceTemperature;
|
||||
}
|
||||
|
||||
float ColorGrading::getWhiteBalanceTint() const noexcept {
|
||||
return mSettings.whiteBalanceTint;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getChannelMixerOutRed() const noexcept {
|
||||
return mSettings.channelMixerOutRed;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getChannelMixerOutGreen() const noexcept {
|
||||
return mSettings.channelMixerOutGreen;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getChannelMixerOutBlue() const noexcept {
|
||||
return mSettings.channelMixerOutBlue;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getShadows() const noexcept {
|
||||
return mSettings.shadows;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getMidtones() const noexcept {
|
||||
return mSettings.midtones;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getHighlights() const noexcept {
|
||||
return mSettings.highlights;
|
||||
}
|
||||
|
||||
math::float4 ColorGrading::getShadowMidtonesHighlightsRanges() const noexcept {
|
||||
return mSettings.ShadowMidtonesHighlightsRanges;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getSlope() const noexcept {
|
||||
return mSettings.slope;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getOffset() const noexcept {
|
||||
return mSettings.offset;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getPower() const noexcept {
|
||||
return mSettings.power;
|
||||
}
|
||||
|
||||
float ColorGrading::getContrast() const noexcept {
|
||||
return mSettings.contrast;
|
||||
}
|
||||
|
||||
float ColorGrading::getVibrance() const noexcept {
|
||||
return mSettings.vibrance;
|
||||
}
|
||||
|
||||
float ColorGrading::getSaturation() const noexcept {
|
||||
return mSettings.saturation;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getCurvesShadowGamma() const noexcept {
|
||||
return mSettings.curvesShadowGamma;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getCurvesMidPoint() const noexcept {
|
||||
return mSettings.curvesMidPoint;
|
||||
}
|
||||
|
||||
math::float3 ColorGrading::getCurvesHighlightScale() const noexcept {
|
||||
return mSettings.curvesHighlightScale;
|
||||
}
|
||||
|
||||
const color::ColorSpace& ColorGrading::getOutputColorSpace() const noexcept {
|
||||
return mSettings.colorSpace;
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
@@ -287,30 +391,25 @@ ColorGrading* ColorGrading::Builder::build(Engine& engine) {
|
||||
if (needToneMapper) {
|
||||
switch (mImpl->toneMapping) {
|
||||
case ToneMapping::LINEAR:
|
||||
mImpl->toneMapper = new LinearToneMapper();
|
||||
mImpl->toneMapper = std::make_shared<LinearToneMapper>();
|
||||
break;
|
||||
case ToneMapping::ACES_LEGACY:
|
||||
mImpl->toneMapper = new ACESLegacyToneMapper();
|
||||
mImpl->toneMapper = std::make_shared<ACESLegacyToneMapper>();
|
||||
break;
|
||||
case ToneMapping::ACES:
|
||||
mImpl->toneMapper = new ACESToneMapper();
|
||||
mImpl->toneMapper = std::make_shared<ACESToneMapper>();
|
||||
break;
|
||||
case ToneMapping::FILMIC:
|
||||
mImpl->toneMapper = new FilmicToneMapper();
|
||||
mImpl->toneMapper = std::make_shared<FilmicToneMapper>();
|
||||
break;
|
||||
case ToneMapping::DISPLAY_RANGE:
|
||||
mImpl->toneMapper = new DisplayRangeToneMapper();
|
||||
mImpl->toneMapper = std::make_shared<DisplayRangeToneMapper>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FColorGrading* colorGrading = downcast(engine).createColorGrading(*this);
|
||||
|
||||
if (needToneMapper) {
|
||||
delete mImpl->toneMapper;
|
||||
mImpl->toneMapper = nullptr;
|
||||
}
|
||||
|
||||
return colorGrading;
|
||||
}
|
||||
|
||||
@@ -886,6 +985,9 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) {
|
||||
data, lutElementCount * elementSize, format, type,
|
||||
[](void* buffer, size_t, void*) { free(buffer); }
|
||||
});
|
||||
|
||||
// Initialize settings from builder
|
||||
initializeSettings(builder, mSettings);
|
||||
}
|
||||
|
||||
FColorGrading::~FColorGrading() noexcept = default;
|
||||
@@ -895,4 +997,33 @@ void FColorGrading::terminate(FEngine& engine) {
|
||||
driver.destroyTexture(mLutHandle);
|
||||
}
|
||||
|
||||
void FColorGrading::initializeSettings(const Builder& builder, Settings& settings) noexcept {
|
||||
settings.lutFormat = builder->format;
|
||||
settings.lutDimensions = builder->dimension;
|
||||
settings.toneMapper = builder->toneMapper;
|
||||
settings.luminanceScaling = builder->luminanceScaling;
|
||||
settings.gummapMapping = builder->gamutMapping;
|
||||
settings.exposure = builder->exposure;
|
||||
settings.nightAdaptation = builder->nightAdaptation;
|
||||
settings.whiteBalanceTemperature = builder->whiteBalance.x;
|
||||
settings.whiteBalanceTint = builder->whiteBalance.y;
|
||||
settings.channelMixerOutRed = builder->outRed;
|
||||
settings.channelMixerOutGreen = builder->outGreen;
|
||||
settings.channelMixerOutBlue = builder->outBlue;
|
||||
settings.shadows = builder->shadows;
|
||||
settings.midtones = builder->midtones;
|
||||
settings.highlights = builder->highlights;
|
||||
settings.ShadowMidtonesHighlightsRanges = builder->tonalRanges;
|
||||
settings.slope = builder->slope;
|
||||
settings.offset = builder->offset;
|
||||
settings.power = builder->power;
|
||||
settings.contrast = builder->contrast;
|
||||
settings.vibrance = builder->vibrance;
|
||||
settings.saturation = builder->saturation;
|
||||
settings.curvesShadowGamma = builder->shadowGamma;
|
||||
settings.curvesMidPoint = builder->midPoint;
|
||||
settings.curvesHighlightScale = builder->highlightScale;
|
||||
settings.colorSpace = builder->outputColorSpace;
|
||||
}
|
||||
|
||||
} //namespace filament
|
||||
|
||||
@@ -51,6 +51,8 @@ private:
|
||||
uint32_t mDimension;
|
||||
bool mIsOneDimensional;
|
||||
bool mIsLDR;
|
||||
|
||||
static void initializeSettings(const Builder& builder, Settings& settings) noexcept;
|
||||
};
|
||||
|
||||
FILAMENT_DOWNCAST(ColorGrading)
|
||||
|
||||
@@ -361,8 +361,6 @@ void FEngine::init() {
|
||||
}
|
||||
|
||||
// initialize the dummy textures so that their contents are not undefined
|
||||
static constexpr uint32_t zeroes[6] = {};
|
||||
static constexpr uint32_t ones = 0xffffffff;
|
||||
|
||||
mDefaultIblTexture = downcast(Texture::Builder()
|
||||
.width(1).height(1).levels(1)
|
||||
@@ -371,7 +369,8 @@ void FEngine::init() {
|
||||
.build(*this));
|
||||
|
||||
driverApi.update3DImage(mDefaultIblTexture->getHwHandle(), 0, 0, 0, 0, 1, 1, 6,
|
||||
{ zeroes, sizeof(zeroes), Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
{ std::array<uint8_t, 6>{}.data(), 6,
|
||||
Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
|
||||
// 3 bands = 9 float3
|
||||
constexpr float sh[9 * 3] = { 0.0f };
|
||||
@@ -393,10 +392,12 @@ void FEngine::init() {
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
driverApi.update3DImage(mDummyOneTexture, 0, 0, 0, 0, 1, 1, 1,
|
||||
{ &ones, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
{ std::array<uint8_t, 4>{0xff, 0xff, 0xff, 0xff}.data(), 4,
|
||||
Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
|
||||
driverApi.update3DImage(mDummyZeroTexture, 0, 0, 0, 0, 1, 1, 1,
|
||||
{ zeroes, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
{ std::array<uint8_t, 4>{}.data(), 4,
|
||||
Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
|
||||
|
||||
mPerViewDescriptorSetLayoutSsrVariant = {
|
||||
@@ -423,25 +424,28 @@ void FEngine::init() {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mDefaultColorGrading = downcast(ColorGrading::Builder().build(*this));
|
||||
|
||||
FMaterial::DefaultMaterialBuilder defaultMaterialBuilder;
|
||||
switch (mConfig.stereoscopicType) {
|
||||
case StereoscopicType::NONE:
|
||||
case StereoscopicType::INSTANCED:
|
||||
defaultMaterialBuilder.package(
|
||||
MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE);
|
||||
MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE);
|
||||
break;
|
||||
case StereoscopicType::MULTIVIEW:
|
||||
#ifdef FILAMENT_ENABLE_MULTIVIEW
|
||||
defaultMaterialBuilder.package(
|
||||
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_DATA, MATERIALS_DEFAULTMATERIAL_MULTIVIEW_SIZE);
|
||||
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_DATA,
|
||||
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_SIZE);
|
||||
#else
|
||||
assert_invariant(false);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
mDefaultMaterial = downcast(defaultMaterialBuilder.build(*this));
|
||||
}
|
||||
|
||||
if (UTILS_UNLIKELY(getSupportedFeatureLevel() >= FeatureLevel::FEATURE_LEVEL_1)) {
|
||||
mDefaultColorGrading = downcast(ColorGrading::Builder().build(*this));
|
||||
|
||||
constexpr float3 dummyPositions[1] = {};
|
||||
constexpr short4 dummyTangents[1] = {};
|
||||
@@ -451,14 +455,26 @@ void FEngine::init() {
|
||||
mDummyOneTextureArray = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
mDummyOneTextureArrayDepth = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
|
||||
TextureFormat::DEPTH32F, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
mDummyZeroTextureArray = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
driverApi.update3DImage(mDummyOneTextureArray, 0, 0, 0, 0, 1, 1, 1,
|
||||
{ &ones, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
{ std::array<uint8_t, 4>{0xff, 0xff, 0xff, 0xff}.data(), 4,
|
||||
Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
|
||||
driverApi.update3DImage(mDummyOneTextureArrayDepth, 0, 0, 0, 0, 1, 1, 1,
|
||||
{ std::array<float, 1>{1.0f}.data(), 4,
|
||||
Texture::Format::DEPTH_COMPONENT, Texture::Type::FLOAT });
|
||||
|
||||
driverApi.update3DImage(mDummyZeroTextureArray, 0, 0, 0, 0, 1, 1, 1,
|
||||
{ zeroes, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
{ std::array<uint8_t, 4>{}.data(), 4,
|
||||
Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
|
||||
mDummyUniformBuffer = driverApi.createBufferObject(CONFIG_MINSPEC_UBO_SIZE,
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
|
||||
|
||||
mLightManager.init(*this);
|
||||
mDFG.init(*this);
|
||||
@@ -608,6 +624,8 @@ void FEngine::shutdown() {
|
||||
driver.destroyTexture(std::move(mDummyZeroTexture));
|
||||
driver.destroyTexture(std::move(mDummyZeroTextureArray));
|
||||
|
||||
driver.destroyBufferObject(std::move(mDummyUniformBuffer));
|
||||
|
||||
driver.destroyRenderTarget(std::move(mDefaultRenderTarget));
|
||||
|
||||
/*
|
||||
@@ -712,8 +730,7 @@ int FEngine::loop() {
|
||||
if (mPlatform == nullptr) {
|
||||
mPlatform = PlatformFactory::create(&mBackend);
|
||||
mOwnPlatform = true;
|
||||
const char* const backend = backendToString(mBackend);
|
||||
slog.i << "FEngine resolved backend: " << backend << io::endl;
|
||||
slog.i << "FEngine resolved backend: " << to_string(mBackend) << io::endl;
|
||||
if (mPlatform == nullptr) {
|
||||
slog.e << "Selected backend not supported in this build." << io::endl;
|
||||
mDriverBarrier.latch();
|
||||
|
||||
@@ -486,10 +486,29 @@ public:
|
||||
return mPerRenderableDescriptorSetLayout;
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> getOneTexture() const { return mDummyOneTexture; }
|
||||
backend::Handle<backend::HwTexture> getZeroTexture() const { return mDummyZeroTexture; }
|
||||
backend::Handle<backend::HwTexture> getOneTextureArray() const { return mDummyOneTextureArray; }
|
||||
backend::Handle<backend::HwTexture> getZeroTextureArray() const { return mDummyZeroTextureArray; }
|
||||
backend::Handle<backend::HwTexture> getOneTexture() const {
|
||||
return mDummyOneTexture;
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> getOneTextureArray() const {
|
||||
return mDummyOneTextureArray;
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> getOneTextureArrayDepth() const {
|
||||
return mDummyOneTextureArrayDepth;
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> getZeroTexture() const {
|
||||
return mDummyZeroTexture;
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> getZeroTextureArray() const {
|
||||
return mDummyZeroTextureArray;
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwBufferObject> getDummyUniformBuffer() const {
|
||||
return mDummyUniformBuffer;
|
||||
}
|
||||
|
||||
static constexpr size_t MiB = 1024u * 1024u;
|
||||
size_t getMinCommandBufferSize() const noexcept { return mConfig.minCommandBufferSizeMB * MiB; }
|
||||
@@ -628,8 +647,10 @@ private:
|
||||
|
||||
backend::Handle<backend::HwTexture> mDummyOneTexture;
|
||||
backend::Handle<backend::HwTexture> mDummyOneTextureArray;
|
||||
backend::Handle<backend::HwTexture> mDummyOneTextureArrayDepth;
|
||||
backend::Handle<backend::HwTexture> mDummyZeroTextureArray;
|
||||
backend::Handle<backend::HwTexture> mDummyZeroTexture;
|
||||
backend::Handle<backend::HwBufferObject> mDummyUniformBuffer;
|
||||
|
||||
std::thread::id mMainThreadId{};
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ static std::unique_ptr<MaterialParser> createParser(Backend const backend,
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(
|
||||
materialResult != MaterialParser::ParseResult::ERROR_MISSING_BACKEND)
|
||||
<< "the material was not built for any of the " << backendToString(backend)
|
||||
<< "the material was not built for any of the " << to_string(backend)
|
||||
<< " backend's supported shader languages (" << languageNames.c_str() << ")\n";
|
||||
}
|
||||
|
||||
@@ -329,11 +329,12 @@ FMaterial::FMaterial(FEngine& engine, const Builder& builder,
|
||||
|
||||
parser->hasCustomDepthShader(&mHasCustomDepthShader);
|
||||
|
||||
mPerViewLayoutIndex = ColorPassDescriptorSet::getIndex(
|
||||
mIsVariantLit,
|
||||
mReflectionMode == ReflectionMode::SCREEN_SPACE ||
|
||||
mRefractionMode == RefractionMode::SCREEN_SPACE,
|
||||
!(mVariantFilterMask & +UserVariantFilterBit::FOG));
|
||||
bool const isLit = mIsVariantLit || mHasShadowMultiplier;
|
||||
bool const isSSR = mReflectionMode == ReflectionMode::SCREEN_SPACE ||
|
||||
mRefractionMode == RefractionMode::SCREEN_SPACE;
|
||||
bool const hasFog = !(mVariantFilterMask & UserVariantFilterMask(UserVariantFilterBit::FOG));
|
||||
|
||||
mPerViewLayoutIndex = ColorPassDescriptorSet::getIndex(isLit, isSSR, hasFog);
|
||||
|
||||
processBlendingMode(parser);
|
||||
processSpecializationConstants(engine, builder, parser);
|
||||
@@ -407,6 +408,7 @@ void FMaterial::terminate(FEngine& engine) {
|
||||
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
mPerViewDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver);
|
||||
mPerViewDescriptorSetLayoutVsm.terminate(engine.getDescriptorSetLayoutFactory(), driver);
|
||||
mDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver);
|
||||
}
|
||||
|
||||
@@ -1149,17 +1151,23 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
|
||||
backend::DescriptorSetLayout descriptorSetLayout;
|
||||
success = parser->getDescriptorSetLayout(&descriptorSetLayout);
|
||||
assert_invariant(success);
|
||||
auto perMatLabel = mName;
|
||||
perMatLabel.append("_perMat");
|
||||
descriptorSetLayout.label = std::move(perMatLabel);
|
||||
|
||||
// get the PER_VIEW descriptor binding info
|
||||
auto perViewDescriptorSetLayout =
|
||||
descriptor_sets::getPerViewDescriptorSetLayout(mMaterialDomain, mVariantFilterMask,
|
||||
mIsVariantLit || mHasShadowMultiplier, mReflectionMode, mRefractionMode);
|
||||
auto perViewLabel = mName;
|
||||
perViewLabel.append("_perView");
|
||||
perViewDescriptorSetLayout.label = std::move(perViewLabel);
|
||||
bool const isLit = mIsVariantLit || mHasShadowMultiplier;
|
||||
bool const isSSR = mReflectionMode == ReflectionMode::SCREEN_SPACE ||
|
||||
mRefractionMode == RefractionMode::SCREEN_SPACE;
|
||||
bool const hasFog = !(mVariantFilterMask & UserVariantFilterMask(UserVariantFilterBit::FOG));
|
||||
|
||||
auto perViewDescriptorSetLayout = descriptor_sets::getPerViewDescriptorSetLayout(
|
||||
mMaterialDomain, isLit, isSSR, hasFog, false);
|
||||
|
||||
auto perViewDescriptorSetLayoutVsm = descriptor_sets::getPerViewDescriptorSetLayout(
|
||||
mMaterialDomain, isLit, isSSR, hasFog, true);
|
||||
|
||||
// set the labels
|
||||
descriptorSetLayout.label = CString{ mName }.append("_perMat");
|
||||
perViewDescriptorSetLayout.label = CString{ mName }.append("_perView");
|
||||
perViewDescriptorSetLayoutVsm.label = CString{ mName }.append("_perViewVsm");
|
||||
|
||||
// get the PER_RENDERABLE and PER_VIEW descriptor binding info
|
||||
for (auto&& [bindingPoint, descriptorSetLayout] : {
|
||||
@@ -1181,7 +1189,11 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
|
||||
|
||||
mPerViewDescriptorSetLayout = {
|
||||
engine.getDescriptorSetLayoutFactory(),
|
||||
engine.getDriverApi(), perViewDescriptorSetLayout };
|
||||
engine.getDriverApi(), std::move(perViewDescriptorSetLayout) };
|
||||
|
||||
mPerViewDescriptorSetLayoutVsm = {
|
||||
engine.getDescriptorSetLayoutFactory(),
|
||||
engine.getDriverApi(), std::move(perViewDescriptorSetLayoutVsm) };
|
||||
}
|
||||
|
||||
descriptor_binding_t FMaterial::getSamplerBinding(
|
||||
|
||||
@@ -93,7 +93,8 @@ public:
|
||||
return mPerViewDescriptorSetLayout;
|
||||
}
|
||||
|
||||
DescriptorSetLayout const& getPerViewDescriptorSetLayout(Variant const variant) const noexcept {
|
||||
DescriptorSetLayout const& getPerViewDescriptorSetLayout(
|
||||
Variant const variant, bool const useVsmDescriptorSetLayout) const noexcept {
|
||||
if (Variant::isValidDepthVariant(variant)) {
|
||||
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
|
||||
return mEngine.getPerViewDescriptorSetLayoutDepthVariant();
|
||||
@@ -102,6 +103,10 @@ public:
|
||||
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
|
||||
return mEngine.getPerViewDescriptorSetLayoutSsrVariant();
|
||||
}
|
||||
if (useVsmDescriptorSetLayout) {
|
||||
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
|
||||
return mPerViewDescriptorSetLayoutVsm;
|
||||
}
|
||||
return mPerViewDescriptorSetLayout;
|
||||
}
|
||||
|
||||
@@ -312,6 +317,7 @@ private:
|
||||
// try to order by frequency of use
|
||||
mutable std::array<backend::Handle<backend::HwProgram>, VARIANT_COUNT> mCachedPrograms;
|
||||
DescriptorSetLayout mPerViewDescriptorSetLayout;
|
||||
DescriptorSetLayout mPerViewDescriptorSetLayoutVsm;
|
||||
DescriptorSetLayout mDescriptorSetLayout;
|
||||
backend::Program::DescriptorSetInfo mProgramDescriptorBindings;
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
using namespace filament::math;
|
||||
using namespace utils;
|
||||
|
||||
@@ -74,15 +76,17 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material,
|
||||
|
||||
FEngine::DriverApi& driver = engine.getDriverApi();
|
||||
|
||||
if (!material->getUniformInterfaceBlock().isEmpty()) {
|
||||
mUniforms = UniformBuffer(material->getUniformInterfaceBlock().getSize());
|
||||
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
|
||||
driver.setDebugTag(mUbHandle.getId(), material->getName());
|
||||
}
|
||||
// even if the material doesn't have any parameters, we allocate a small UBO because it's
|
||||
// expected by the per-material descriptor-set layout
|
||||
size_t const uboSize = std::max(size_t(16), material->getUniformInterfaceBlock().getSize());
|
||||
mUniforms = UniformBuffer(uboSize);
|
||||
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
|
||||
driver.setDebugTag(mUbHandle.getId(), material->getName());
|
||||
|
||||
// set the UBO, always descriptor 0
|
||||
mDescriptorSet.setBuffer(0, mUbHandle, 0, mUniforms.getSize());
|
||||
mDescriptorSet.setBuffer(material->getDescriptorSetLayout(),
|
||||
0, mUbHandle, 0, mUniforms.getSize());
|
||||
|
||||
const RasterState& rasterState = material->getRasterState();
|
||||
// At the moment, only MaterialInstances have a stencil state, but in the future it should be
|
||||
@@ -142,15 +146,15 @@ FMaterialInstance::FMaterialInstance(FEngine& engine,
|
||||
FEngine::DriverApi& driver = engine.getDriverApi();
|
||||
FMaterial const* const material = other->getMaterial();
|
||||
|
||||
if (!material->getUniformInterfaceBlock().isEmpty()) {
|
||||
mUniforms.setUniforms(other->getUniformBuffer());
|
||||
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
|
||||
driver.setDebugTag(mUbHandle.getId(), material->getName());
|
||||
}
|
||||
size_t const uboSize = std::max(size_t(16), material->getUniformInterfaceBlock().getSize());
|
||||
mUniforms = UniformBuffer(uboSize);
|
||||
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
|
||||
driver.setDebugTag(mUbHandle.getId(), material->getName());
|
||||
|
||||
// set the UBO, always descriptor 0
|
||||
mDescriptorSet.setBuffer(0, mUbHandle, 0, mUniforms.getSize());
|
||||
mDescriptorSet.setBuffer(mMaterial->getDescriptorSetLayout(),
|
||||
0, mUbHandle, 0, mUniforms.getSize());
|
||||
|
||||
if (material->hasDoubleSidedCapability()) {
|
||||
setDoubleSided(mIsDoubleSided);
|
||||
@@ -223,7 +227,8 @@ void FMaterialInstance::commit(DriverApi& driver) const {
|
||||
<< "Invalid texture still bound to MaterialInstance: '" << getName() << "'\n";
|
||||
Handle<HwTexture> const handle = p.texture->getHwHandleForSampling();
|
||||
assert_invariant(handle);
|
||||
mDescriptorSet.setSampler(binding, handle, p.params);
|
||||
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
|
||||
binding, handle, p.params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +244,9 @@ void FMaterialInstance::commit(DriverApi& driver) const {
|
||||
void FMaterialInstance::setParameter(std::string_view const name,
|
||||
Handle<HwTexture> texture, SamplerParams const params) {
|
||||
auto const binding = mMaterial->getSamplerBinding(name);
|
||||
mDescriptorSet.setSampler(binding, texture, params);
|
||||
|
||||
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
|
||||
binding, texture, params);
|
||||
}
|
||||
|
||||
void FMaterialInstance::setParameterImpl(std::string_view const name,
|
||||
@@ -266,6 +273,21 @@ void FMaterialInstance::setParameterImpl(std::string_view const name,
|
||||
#endif
|
||||
|
||||
auto const binding = mMaterial->getSamplerBinding(name);
|
||||
|
||||
if (texture) {
|
||||
auto const& descriptorSetLayout = mMaterial->getDescriptorSetLayout();
|
||||
DescriptorType const descriptorType = descriptorSetLayout.getDescriptorType(binding);
|
||||
TextureType const textureType = texture->getTextureType();
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(
|
||||
DescriptorSet::isTextureCompatibleWithDescriptor(textureType, descriptorType))
|
||||
<< "Texture format " << int(texture->getFormat())
|
||||
<< " of type " << to_string(textureType)
|
||||
<< " is not compatible with material \"" << getMaterial()->getName().c_str() << "\""
|
||||
<< " parameter \"" << name << "\""
|
||||
<< " of type " << to_string(descriptorType);
|
||||
}
|
||||
|
||||
if (texture && texture->textureHandleCanMutate()) {
|
||||
mTextureParameters[binding] = { texture, sampler.getSamplerParams() };
|
||||
} else {
|
||||
@@ -278,7 +300,8 @@ void FMaterialInstance::setParameterImpl(std::string_view const name,
|
||||
handle = texture->getHwHandleForSampling();
|
||||
assert_invariant(handle == texture->getHwHandle());
|
||||
}
|
||||
mDescriptorSet.setSampler(binding, handle, sampler.getSamplerParams());
|
||||
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
|
||||
binding, handle, sampler.getSamplerParams());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,29 +418,30 @@ void FMaterialInstance::fixMissingSamplers() const {
|
||||
auto const pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
|
||||
return item.binding == binding;
|
||||
});
|
||||
|
||||
FEngine const& engine = mMaterial->getEngine();
|
||||
|
||||
// just safety-check, should never fail
|
||||
if (UTILS_LIKELY(pos != list.end())) {
|
||||
switch (pos->type) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
mDescriptorSet.setSampler(binding,
|
||||
engine.getZeroTexture(), {});
|
||||
break;
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
mDescriptorSet.setSampler(binding,
|
||||
engine.getZeroTextureArray(), {});
|
||||
break;
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
mDescriptorSet.setSampler(binding,
|
||||
engine.getDummyCubemap()->getHwHandle(), {});
|
||||
break;
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
case SamplerType::SAMPLER_3D:
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
// we're currently not able to fix-up those
|
||||
break;
|
||||
FEngine const& engine = mMaterial->getEngine();
|
||||
filament::DescriptorSetLayout const& layout = mMaterial->getDescriptorSetLayout();
|
||||
|
||||
if (pos->format != SamplerFormat::FLOAT) {
|
||||
// TODO: we only handle missing samplers that are FLOAT
|
||||
switch (pos->type) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
mDescriptorSet.setSampler(layout,
|
||||
binding, engine.getZeroTexture(), {});
|
||||
break;
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
mDescriptorSet.setSampler(layout,
|
||||
binding, engine.getZeroTextureArray(), {});
|
||||
break;
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
mDescriptorSet.setSampler(layout,
|
||||
binding, engine.getDummyCubemap()->getHwHandle(), {});
|
||||
break;
|
||||
default:
|
||||
// we're currently not able to fix-up other sampler types
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -114,7 +114,8 @@ FMorphTargetBuffer::FMorphTargetBuffer(FEngine& engine, const Builder& builder)
|
||||
: mVertexCount(builder->mVertexCount),
|
||||
mCount(builder->mCount) {
|
||||
|
||||
if (UTILS_UNLIKELY(engine.getActiveFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0)) {
|
||||
if (UTILS_UNLIKELY(engine.getSupportedFeatureLevel() <= FeatureLevel::FEATURE_LEVEL_0)) {
|
||||
// feature level 0 doesn't support morph target buffers
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -977,7 +977,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
// this descriptor-set is also used for ssr/picking/structure and these could be stale
|
||||
// it would be better to use a separate desriptor-set for those two cases so that we don't
|
||||
// have to do this
|
||||
view.unbindSamplers(driver);
|
||||
view.unbindSamplers(engine);
|
||||
view.commitUniformsAndSamplers(driver);
|
||||
});
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ using namespace math;
|
||||
|
||||
// this is a hack to be able to create a std::function<> with a non-copyable closure
|
||||
template<class F>
|
||||
auto make_copyable_function(F&& f) {
|
||||
static auto make_copyable_function(F&& f) {
|
||||
using dF = std::decay_t<F>;
|
||||
auto spf = std::make_shared<dF>(std::forward<F>(f));
|
||||
return [spf](auto&& ... args) -> decltype(auto) {
|
||||
@@ -274,7 +274,9 @@ Texture* Texture::Builder::build(Engine& engine) {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
FTexture::FTexture(FEngine& engine, const Builder& builder) {
|
||||
FTexture::FTexture(FEngine& engine, const Builder& builder)
|
||||
: mHasBlitSrc(false),
|
||||
mExternal(false) {
|
||||
FEngine::DriverApi& driver = engine.getDriverApi();
|
||||
mDriver = &driver; // this is unfortunately needed for getHwHandleForSampling()
|
||||
mWidth = static_cast<uint32_t>(builder->mWidth);
|
||||
@@ -288,6 +290,7 @@ FTexture::FTexture(FEngine& engine, const Builder& builder) {
|
||||
mTextureIsSwizzled = builder->mTextureIsSwizzled;
|
||||
mHasBlitSrc = builder->mHasBlitSrc;
|
||||
mExternal = builder->mExternal;
|
||||
mTextureType = backend::getTextureType(mFormat);
|
||||
|
||||
bool const isImported = builder->mImportedId != 0;
|
||||
if (mExternal && !isImported) {
|
||||
@@ -716,6 +719,10 @@ size_t FTexture::getFormatSize(InternalFormat const format) noexcept {
|
||||
return backend::getFormatSize(format);
|
||||
}
|
||||
|
||||
TextureType FTexture::getTextureType() const noexcept {
|
||||
return mTextureType;
|
||||
}
|
||||
|
||||
|
||||
void FTexture::generatePrefilterMipmap(FEngine& engine,
|
||||
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -105,18 +108,20 @@ public:
|
||||
// Size a of a pixel in bytes for the given format
|
||||
static size_t getFormatSize(InternalFormat format) noexcept;
|
||||
|
||||
backend::TextureType getTextureType() const noexcept;
|
||||
|
||||
// Returns the with or height for a given mipmap level from the base value.
|
||||
static inline size_t valueForLevel(uint8_t const level, size_t const baseLevelValue) {
|
||||
static size_t valueForLevel(uint8_t const level, size_t const baseLevelValue) {
|
||||
return std::max(size_t(1), baseLevelValue >> level);
|
||||
}
|
||||
|
||||
// Returns the max number of levels for a texture of given max dimensions
|
||||
static inline uint8_t maxLevelCount(uint32_t const maxDimension) noexcept {
|
||||
static uint8_t maxLevelCount(uint32_t const maxDimension) noexcept {
|
||||
return std::max(1, std::ilogbf(float(maxDimension)) + 1);
|
||||
}
|
||||
|
||||
// Returns the max number of levels for a texture of given dimensions
|
||||
static inline uint8_t maxLevelCount(uint32_t const width, uint32_t const height) noexcept {
|
||||
static uint8_t maxLevelCount(uint32_t const width, uint32_t const height) noexcept {
|
||||
uint32_t const maxDimension = std::max(width, height);
|
||||
return maxLevelCount(maxDimension);
|
||||
}
|
||||
@@ -132,7 +137,7 @@ public:
|
||||
void updateLodRange(uint8_t level) noexcept;
|
||||
|
||||
// TODO: remove in a future filament release. See below for description.
|
||||
inline bool hasBlitSrcUsage() const noexcept {
|
||||
bool hasBlitSrcUsage() const noexcept {
|
||||
return mHasBlitSrc;
|
||||
}
|
||||
|
||||
@@ -166,23 +171,25 @@ private:
|
||||
uint32_t mWidth = 1;
|
||||
uint32_t mHeight = 1;
|
||||
uint32_t mDepth = 1;
|
||||
|
||||
InternalFormat mFormat = InternalFormat::RGBA8;
|
||||
Sampler mTarget = Sampler::SAMPLER_2D;
|
||||
uint8_t mLevelCount = 1;
|
||||
uint8_t mSampleCount = 1;
|
||||
|
||||
std::array<Swizzle, 4> mSwizzle = {
|
||||
Swizzle::CHANNEL_0, Swizzle::CHANNEL_1,
|
||||
Swizzle::CHANNEL_2, Swizzle::CHANNEL_3 };
|
||||
bool mTextureIsSwizzled;
|
||||
|
||||
Usage mUsage = Usage::DEFAULT;
|
||||
backend::TextureType mTextureType;
|
||||
|
||||
// TODO: remove in a future filament release.
|
||||
// Indicates whether the user has set the TextureUsage::BLIT_SRC usage. This will be used to
|
||||
// temporarily validate whether this texture can be used for readPixels.
|
||||
bool mHasBlitSrc = false;
|
||||
bool mExternal = false;
|
||||
// there is 4 bytes of padding here
|
||||
bool mHasBlitSrc : 1;
|
||||
bool mExternal : 1;
|
||||
bool mTextureIsSwizzled : 1;
|
||||
|
||||
FStream* mStream = nullptr; // only needed for streaming textures
|
||||
};
|
||||
|
||||
+105
-44
@@ -68,10 +68,36 @@ FView::FView(FEngine& engine)
|
||||
mFogEntity(engine.getEntityManager().create()),
|
||||
mIsStereoSupported(engine.getDriverApi().isStereoSupported()),
|
||||
mUniforms(engine.getDriverApi()),
|
||||
mColorPassDescriptorSet(engine, mUniforms) {
|
||||
|
||||
mColorPassDescriptorSet{
|
||||
{ engine, false, mUniforms },
|
||||
{ engine, true, mUniforms } }
|
||||
{
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
|
||||
auto const& layout = engine.getPerRenderableDescriptorSetLayout();
|
||||
|
||||
// initialize the common descriptor set with dummy descriptors
|
||||
mCommonRenderableDescriptorSet.setBuffer(layout,
|
||||
+PerRenderableBindingPoints::BONES_UNIFORMS,
|
||||
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableBoneUib));
|
||||
|
||||
mCommonRenderableDescriptorSet.setBuffer(layout,
|
||||
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
|
||||
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableMorphingUib));
|
||||
|
||||
mCommonRenderableDescriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
|
||||
engine.getDummyMorphTargetBuffer()->getPositionsHandle(), {});
|
||||
|
||||
mCommonRenderableDescriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
|
||||
engine.getDummyMorphTargetBuffer()->getTangentsHandle(), {});
|
||||
|
||||
mCommonRenderableDescriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
|
||||
engine.getZeroTextureArray(), {});
|
||||
|
||||
|
||||
FDebugRegistry& debugRegistry = engine.getDebugRegistry();
|
||||
|
||||
debugRegistry.registerProperty("d.view.camera_at_origin",
|
||||
@@ -125,11 +151,13 @@ FView::FView(FEngine& engine)
|
||||
|
||||
mDefaultColorGrading = mColorGrading = engine.getDefaultColorGrading();
|
||||
|
||||
mColorPassDescriptorSet.init(
|
||||
engine,
|
||||
mLightUbh,
|
||||
mFroxelizer.getRecordBuffer(),
|
||||
mFroxelizer.getFroxelBuffer());
|
||||
for (auto&& colorPassDescriptorSet : mColorPassDescriptorSet) {
|
||||
colorPassDescriptorSet.init(
|
||||
engine,
|
||||
mLightUbh,
|
||||
mFroxelizer.getRecordBuffer(),
|
||||
mFroxelizer.getFroxelBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
FView::~FView() noexcept = default;
|
||||
@@ -146,7 +174,9 @@ void FView::terminate(FEngine& engine) {
|
||||
|
||||
ShadowMapManager::terminate(engine, mShadowMapManager);
|
||||
mUniforms.terminate(driver);
|
||||
mColorPassDescriptorSet.terminate(engine.getDescriptorSetLayoutFactory(), driver);
|
||||
for (auto&& colorPassDescriptorSet : mColorPassDescriptorSet) {
|
||||
colorPassDescriptorSet.terminate(engine.getDescriptorSetLayoutFactory(), driver);
|
||||
}
|
||||
mFroxelizer.terminate(driver);
|
||||
mCommonRenderableDescriptorSet.terminate(driver);
|
||||
|
||||
@@ -429,7 +459,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
|
||||
*/
|
||||
|
||||
const float exposure = Exposure::exposure(cameraInfo.ev100);
|
||||
mColorPassDescriptorSet.prepareExposure(cameraInfo.ev100);
|
||||
getColorPassDescriptorSet().prepareExposure(cameraInfo.ev100);
|
||||
|
||||
/*
|
||||
* Indirect light (IBL)
|
||||
@@ -446,7 +476,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
|
||||
FSkybox const* const skybox = scene->getSkybox();
|
||||
intensity = skybox ? skybox->getIntensity() : FIndirectLight::DEFAULT_INTENSITY;
|
||||
}
|
||||
mColorPassDescriptorSet.prepareAmbientLight(engine, *ibl, intensity, exposure);
|
||||
getColorPassDescriptorSet().prepareAmbientLight(engine, *ibl, intensity, exposure);
|
||||
|
||||
/*
|
||||
* Directional light (always at index 0)
|
||||
@@ -454,7 +484,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
|
||||
|
||||
FLightManager::Instance const directionalLight = lightData.elementAt<FScene::LIGHT_INSTANCE>(0);
|
||||
const float3 sceneSpaceDirection = lightData.elementAt<FScene::DIRECTION>(0); // guaranteed normalized
|
||||
mColorPassDescriptorSet.prepareDirectionalLight(engine, exposure, sceneSpaceDirection, directionalLight);
|
||||
getColorPassDescriptorSet().prepareDirectionalLight(engine, exposure, sceneSpaceDirection, directionalLight);
|
||||
}
|
||||
|
||||
CameraInfo FView::computeCameraInfo(FEngine& engine) const noexcept {
|
||||
@@ -606,7 +636,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
|
||||
cameraInfo.projection, cameraInfo.zn, cameraInfo.zf)) {
|
||||
// TODO: might be more consistent to do this in prepareLighting(), but it's not
|
||||
// strictly necessary
|
||||
mColorPassDescriptorSet.prepareDynamicLights(mFroxelizer);
|
||||
getColorPassDescriptorSet().prepareDynamicLights(mFroxelizer);
|
||||
}
|
||||
// We need to pass viewMatrix by value here because it extends the scope of this
|
||||
// function.
|
||||
@@ -711,6 +741,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
|
||||
scene->updateUBOs(merged, mRenderableUbh);
|
||||
|
||||
mCommonRenderableDescriptorSet.setBuffer(
|
||||
engine.getPerRenderableDescriptorSetLayout(),
|
||||
+PerRenderableBindingPoints::OBJECT_UNIFORMS, mRenderableUbh,
|
||||
0, sizeof(PerRenderableUib));
|
||||
|
||||
@@ -734,37 +765,65 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
|
||||
FRenderableManager& rcm = engine.getRenderableManager();
|
||||
auto& descriptorSet = rcm.getDescriptorSet(ci);
|
||||
|
||||
auto const& layout = engine.getPerRenderableDescriptorSetLayout();
|
||||
|
||||
// initialize the descriptor set the first time it's needed
|
||||
if (UTILS_UNLIKELY(!descriptorSet.getHandle())) {
|
||||
descriptorSet = DescriptorSet{ engine.getPerRenderableDescriptorSetLayout() };
|
||||
descriptorSet = DescriptorSet{ layout };
|
||||
}
|
||||
|
||||
descriptorSet.setBuffer(+PerRenderableBindingPoints::OBJECT_UNIFORMS,
|
||||
descriptorSet.setBuffer(layout,
|
||||
+PerRenderableBindingPoints::OBJECT_UNIFORMS,
|
||||
instance.handle ? instance.handle : mRenderableUbh,
|
||||
0, sizeof(PerRenderableUib));
|
||||
|
||||
if (UTILS_UNLIKELY(skinning.handle || morphing.handle)) {
|
||||
descriptorSet.setBuffer(layout,
|
||||
+PerRenderableBindingPoints::BONES_UNIFORMS,
|
||||
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableBoneUib));
|
||||
|
||||
descriptorSet.setBuffer(+PerRenderableBindingPoints::BONES_UNIFORMS,
|
||||
descriptorSet.setBuffer(layout,
|
||||
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
|
||||
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableMorphingUib));
|
||||
|
||||
descriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
|
||||
engine.getDummyMorphTargetBuffer()->getPositionsHandle(), {});
|
||||
|
||||
descriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
|
||||
engine.getDummyMorphTargetBuffer()->getTangentsHandle(), {});
|
||||
|
||||
descriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
|
||||
engine.getZeroTextureArray(), {});
|
||||
|
||||
if (UTILS_UNLIKELY(skinning.handle || morphing.handle)) {
|
||||
descriptorSet.setBuffer(layout,
|
||||
+PerRenderableBindingPoints::BONES_UNIFORMS,
|
||||
skinning.handle, 0, sizeof(PerRenderableBoneUib));
|
||||
|
||||
descriptorSet.setSampler(+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
|
||||
descriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
|
||||
skinning.boneIndicesAndWeightHandle, {});
|
||||
|
||||
descriptorSet.setBuffer(+PerRenderableBindingPoints::MORPHING_UNIFORMS,
|
||||
descriptorSet.setBuffer(layout,
|
||||
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
|
||||
morphing.handle, 0, sizeof(PerRenderableMorphingUib));
|
||||
|
||||
descriptorSet.setSampler(+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
|
||||
descriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
|
||||
morphing.morphTargetBuffer->getPositionsHandle(), {});
|
||||
|
||||
descriptorSet.setSampler(+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
|
||||
descriptorSet.setSampler(layout,
|
||||
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
|
||||
morphing.morphTargetBuffer->getTangentsHandle(), {});
|
||||
}
|
||||
|
||||
descriptorSet.commit(engine.getPerRenderableDescriptorSetLayout(), driver);
|
||||
descriptorSet.commit(layout, driver);
|
||||
|
||||
// write the descriptor-set handle to the sceneData array for access later
|
||||
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) = descriptorSet.getHandle();
|
||||
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) =
|
||||
descriptorSet.getHandle();
|
||||
} else {
|
||||
// use the shared descriptor-set
|
||||
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) =
|
||||
@@ -788,12 +847,13 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
|
||||
auto const& tcm = engine.getTransformManager();
|
||||
auto const fogTransform = tcm.getWorldTransformAccurate(tcm.getInstance(mFogEntity));
|
||||
|
||||
mColorPassDescriptorSet.prepareTime(engine, userTime);
|
||||
mColorPassDescriptorSet.prepareFog(engine, cameraInfo, fogTransform, mFogOptions,
|
||||
auto& colorPassDescriptorSet = getColorPassDescriptorSet();
|
||||
colorPassDescriptorSet.prepareTime(engine, userTime);
|
||||
colorPassDescriptorSet.prepareFog(engine, cameraInfo, fogTransform, mFogOptions,
|
||||
scene->getIndirectLight());
|
||||
mColorPassDescriptorSet.prepareTemporalNoise(engine, mTemporalAntiAliasingOptions);
|
||||
mColorPassDescriptorSet.prepareBlending(needsAlphaChannel);
|
||||
mColorPassDescriptorSet.prepareMaterialGlobals(mMaterialGlobals);
|
||||
colorPassDescriptorSet.prepareTemporalNoise(engine, mTemporalAntiAliasingOptions);
|
||||
colorPassDescriptorSet.prepareBlending(needsAlphaChannel);
|
||||
colorPassDescriptorSet.prepareMaterialGlobals(mMaterialGlobals);
|
||||
}
|
||||
|
||||
void FView::computeVisibilityMasks(
|
||||
@@ -854,12 +914,12 @@ void FView::prepareUpscaler(float2 const scale,
|
||||
derivativesScale = 0.5f;
|
||||
}
|
||||
}
|
||||
mColorPassDescriptorSet.prepareLodBias(bias, derivativesScale);
|
||||
getColorPassDescriptorSet().prepareLodBias(bias, derivativesScale);
|
||||
}
|
||||
|
||||
void FView::prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) const noexcept {
|
||||
SYSTRACE_CALL();
|
||||
mColorPassDescriptorSet.prepareCamera(engine, cameraInfo);
|
||||
getColorPassDescriptorSet().prepareCamera(engine, cameraInfo);
|
||||
}
|
||||
|
||||
void FView::prepareViewport(
|
||||
@@ -868,23 +928,23 @@ void FView::prepareViewport(
|
||||
SYSTRACE_CALL();
|
||||
// TODO: we should pass viewport.{left|bottom} to the backend, so it can offset the
|
||||
// scissor properly.
|
||||
mColorPassDescriptorSet.prepareViewport(physicalViewport, logicalViewport);
|
||||
getColorPassDescriptorSet().prepareViewport(physicalViewport, logicalViewport);
|
||||
}
|
||||
|
||||
void FView::prepareSSAO(Handle<HwTexture> ssao) const noexcept {
|
||||
mColorPassDescriptorSet.prepareSSAO(ssao, mAmbientOcclusionOptions);
|
||||
getColorPassDescriptorSet().prepareSSAO(ssao, mAmbientOcclusionOptions);
|
||||
}
|
||||
|
||||
void FView::prepareSSR(Handle<HwTexture> ssr,
|
||||
bool const disableSSR,
|
||||
float const refractionLodOffset,
|
||||
ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept {
|
||||
mColorPassDescriptorSet.prepareSSR(ssr, disableSSR, refractionLodOffset, ssrOptions);
|
||||
getColorPassDescriptorSet().prepareSSR(ssr, disableSSR, refractionLodOffset, ssrOptions);
|
||||
}
|
||||
|
||||
void FView::prepareStructure(Handle<HwTexture> structure) const noexcept {
|
||||
// sampler must be NEAREST
|
||||
mColorPassDescriptorSet.prepareStructure(structure);
|
||||
getColorPassDescriptorSet().prepareStructure(structure);
|
||||
}
|
||||
|
||||
void FView::prepareShadow(Handle<HwTexture> texture) const noexcept {
|
||||
@@ -896,37 +956,38 @@ void FView::prepareShadow(Handle<HwTexture> texture) const noexcept {
|
||||
}
|
||||
switch (mShadowType) {
|
||||
case ShadowType::PCF:
|
||||
mColorPassDescriptorSet.prepareShadowPCF(texture, uniforms);
|
||||
getColorPassDescriptorSet().prepareShadowPCF(texture, uniforms);
|
||||
break;
|
||||
case ShadowType::VSM:
|
||||
mColorPassDescriptorSet.prepareShadowVSM(texture, uniforms, mVsmShadowOptions);
|
||||
getColorPassDescriptorSet().prepareShadowVSM(texture, uniforms, mVsmShadowOptions);
|
||||
break;
|
||||
case ShadowType::DPCF:
|
||||
mColorPassDescriptorSet.prepareShadowDPCF(texture, uniforms, mSoftShadowOptions);
|
||||
getColorPassDescriptorSet().prepareShadowDPCF(texture, uniforms, mSoftShadowOptions);
|
||||
break;
|
||||
case ShadowType::PCSS:
|
||||
mColorPassDescriptorSet.prepareShadowPCSS(texture, uniforms, mSoftShadowOptions);
|
||||
getColorPassDescriptorSet().prepareShadowPCSS(texture, uniforms, mSoftShadowOptions);
|
||||
break;
|
||||
case ShadowType::PCFd:
|
||||
mColorPassDescriptorSet.prepareShadowPCFDebug(texture, uniforms);
|
||||
getColorPassDescriptorSet().prepareShadowPCFDebug(texture, uniforms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FView::prepareShadowMapping(bool const highPrecision) const noexcept {
|
||||
void FView::prepareShadowMapping(FEngine const& engine, bool const highPrecision) const noexcept {
|
||||
BufferObjectHandle ubo{ engine.getDummyUniformBuffer() };
|
||||
if (mHasShadowing) {
|
||||
assert_invariant(mShadowMapManager);
|
||||
mColorPassDescriptorSet.prepareShadowMapping(
|
||||
mShadowMapManager->getShadowUniformsHandle(), highPrecision);
|
||||
ubo = mShadowMapManager->getShadowUniformsHandle();
|
||||
}
|
||||
getColorPassDescriptorSet().prepareShadowMapping(ubo, highPrecision);
|
||||
}
|
||||
|
||||
void FView::commitUniformsAndSamplers(DriverApi& driver) const noexcept {
|
||||
mColorPassDescriptorSet.commit(driver);
|
||||
getColorPassDescriptorSet().commit(driver);
|
||||
}
|
||||
|
||||
void FView::unbindSamplers(DriverApi& driver) noexcept {
|
||||
mColorPassDescriptorSet.unbindSamplers(driver);
|
||||
void FView::unbindSamplers(FEngine& engine) noexcept {
|
||||
getColorPassDescriptorSet().unbindSamplers(engine);
|
||||
}
|
||||
|
||||
void FView::commitFroxels(DriverApi& driverApi) const noexcept {
|
||||
|
||||
@@ -178,11 +178,11 @@ public:
|
||||
ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept;
|
||||
void prepareStructure(backend::Handle<backend::HwTexture> structure) const noexcept;
|
||||
void prepareShadow(backend::Handle<backend::HwTexture> structure) const noexcept;
|
||||
void prepareShadowMapping(bool highPrecision) const noexcept;
|
||||
void prepareShadowMapping(FEngine const& engine, bool highPrecision) const noexcept;
|
||||
|
||||
void commitFroxels(backend::DriverApi& driverApi) const noexcept;
|
||||
void commitUniformsAndSamplers(backend::DriverApi& driver) const noexcept;
|
||||
void unbindSamplers(backend::DriverApi& driver) noexcept;
|
||||
void unbindSamplers(FEngine& engine) noexcept;
|
||||
|
||||
utils::JobSystem::Job* getFroxelizerSync() const noexcept { return mFroxelizerSync; }
|
||||
void setFroxelizerSync(utils::JobSystem::Job* sync) noexcept { mFroxelizerSync = sync; }
|
||||
@@ -440,7 +440,9 @@ public:
|
||||
static void cullRenderables(utils::JobSystem& js, FScene::RenderableSoa& renderableData,
|
||||
Frustum const& frustum, size_t bit) noexcept;
|
||||
|
||||
ColorPassDescriptorSet& getColorPassDescriptorSet() noexcept { return mColorPassDescriptorSet; }
|
||||
ColorPassDescriptorSet& getColorPassDescriptorSet() const noexcept {
|
||||
return mColorPassDescriptorSet[mShadowType == ShadowType::PCF ? 0 : 1];
|
||||
}
|
||||
|
||||
// Returns the frame history FIFO. This is typically used by the FrameGraph to access
|
||||
// previous frame data.
|
||||
@@ -587,7 +589,7 @@ private:
|
||||
RenderQuality mRenderQuality;
|
||||
|
||||
mutable TypedUniformBuffer<PerViewUib> mUniforms;
|
||||
mutable ColorPassDescriptorSet mColorPassDescriptorSet;
|
||||
mutable ColorPassDescriptorSet mColorPassDescriptorSet[2];
|
||||
|
||||
mutable FrameHistory mFrameHistory{};
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ uint8_t ColorPassDescriptorSet::getIndex(
|
||||
index |= 0x2;
|
||||
}
|
||||
|
||||
if (!fog) {
|
||||
if (fog) {
|
||||
// this will remove samplers needed for fog
|
||||
index |= 0x4;
|
||||
}
|
||||
@@ -88,27 +88,18 @@ uint8_t ColorPassDescriptorSet::getIndex(
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine,
|
||||
ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine, bool const vsm,
|
||||
TypedUniformBuffer<PerViewUib>& uniforms) noexcept
|
||||
: mUniforms(uniforms) {
|
||||
|
||||
constexpr UserVariantFilterMask filterFog = UserVariantFilterMask(UserVariantFilterBit::FOG);
|
||||
constexpr UserVariantFilterMask keepFog = UserVariantFilterMask(0);
|
||||
|
||||
: mUniforms(uniforms), mIsVsm(vsm) {
|
||||
for (bool const lit: { false, true }) {
|
||||
for (bool const ssr: { false, true }) {
|
||||
for (bool const fog: { false, true }) {
|
||||
auto index = getIndex(lit, ssr, fog);
|
||||
auto const index = getIndex(lit, ssr, fog);
|
||||
mDescriptorSetLayout[index] = {
|
||||
engine.getDescriptorSetLayoutFactory(),
|
||||
engine.getDriverApi(),
|
||||
descriptor_sets::getPerViewDescriptorSetLayout(
|
||||
MaterialDomain::SURFACE,
|
||||
fog ? keepFog : filterFog,
|
||||
lit,
|
||||
ssr ? ReflectionMode::SCREEN_SPACE : ReflectionMode::DEFAULT,
|
||||
ssr ? RefractionMode::SCREEN_SPACE : RefractionMode::NONE)
|
||||
MaterialDomain::SURFACE, lit, ssr, fog, vsm)
|
||||
};
|
||||
mDescriptorSet[index] = DescriptorSet{ mDescriptorSetLayout[index] };
|
||||
}
|
||||
@@ -118,11 +109,11 @@ ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine,
|
||||
setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
|
||||
uniforms.getUboHandle(), 0, uniforms.getSize());
|
||||
|
||||
if (engine.getDFG().isValid()) {
|
||||
TextureSampler const sampler(TextureSampler::MagFilter::LINEAR);
|
||||
setSampler(+PerViewBindingPoints::IBL_DFG_LUT,
|
||||
engine.getDFG().getTexture(), sampler.getSamplerParams());
|
||||
}
|
||||
setSampler(+PerViewBindingPoints::IBL_DFG_LUT,
|
||||
engine.getDFG().isValid() ?
|
||||
engine.getDFG().getTexture() : engine.getZeroTexture(), {
|
||||
.filterMag = SamplerMagFilter::LINEAR
|
||||
});
|
||||
}
|
||||
|
||||
void ColorPassDescriptorSet::init(
|
||||
@@ -130,12 +121,14 @@ void ColorPassDescriptorSet::init(
|
||||
BufferObjectHandle lights,
|
||||
BufferObjectHandle recordBuffer,
|
||||
BufferObjectHandle froxelBuffer) noexcept {
|
||||
for (auto&& descriptorSet: mDescriptorSet) {
|
||||
descriptorSet.setBuffer(+PerViewBindingPoints::LIGHTS,
|
||||
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
|
||||
auto& descriptorSet = mDescriptorSet[i];
|
||||
auto const& layout = mDescriptorSetLayout[i];
|
||||
descriptorSet.setBuffer(layout, +PerViewBindingPoints::LIGHTS,
|
||||
lights, 0, CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib));
|
||||
descriptorSet.setBuffer(+PerViewBindingPoints::RECORD_BUFFER,
|
||||
descriptorSet.setBuffer(layout, +PerViewBindingPoints::RECORD_BUFFER,
|
||||
recordBuffer, 0, sizeof(FroxelRecordUib));
|
||||
descriptorSet.setBuffer(+PerViewBindingPoints::FROXEL_BUFFER,
|
||||
descriptorSet.setBuffer(layout, +PerViewBindingPoints::FROXEL_BUFFER,
|
||||
froxelBuffer, 0, Froxelizer::getFroxelBufferByteCount(engine.getDriverApi()));
|
||||
}
|
||||
}
|
||||
@@ -305,6 +298,7 @@ void ColorPassDescriptorSet::prepareFog(FEngine& engine, const CameraInfo& camer
|
||||
|
||||
void ColorPassDescriptorSet::prepareSSAO(Handle<HwTexture> ssao,
|
||||
AmbientOcclusionOptions const& options) noexcept {
|
||||
|
||||
// High quality sampling is enabled only if AO itself is enabled and upsampling quality is at
|
||||
// least set to high and of course only if upsampling is needed.
|
||||
const bool highQualitySampling = options.upsampling >= QualityLevel::HIGH
|
||||
@@ -537,20 +531,28 @@ void ColorPassDescriptorSet::commit(DriverApi& driver) noexcept {
|
||||
driver.updateBufferObject(mUniforms.getUboHandle(),
|
||||
mUniforms.toBufferDescriptor(driver), 0);
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
|
||||
mDescriptorSet[i].commit(mDescriptorSetLayout[i], driver);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorPassDescriptorSet::unbindSamplers(DriverApi&) noexcept {
|
||||
void ColorPassDescriptorSet::unbindSamplers(FEngine& engine) noexcept {
|
||||
// this needs to reset the sampler that are only set in RendererUtils::colorPass(), because
|
||||
// this descriptor-set is also used for ssr/picking/structure and these could be stale
|
||||
// it would be better to use a separate descriptor-set for those two cases so that we don't
|
||||
// have to do this
|
||||
setSampler(+PerViewBindingPoints::STRUCTURE, {}, {});
|
||||
setSampler(+PerViewBindingPoints::SHADOW_MAP, {}, {});
|
||||
setSampler(+PerViewBindingPoints::SSAO, {}, {});
|
||||
setSampler(+PerViewBindingPoints::SSR, {}, {});
|
||||
setBuffer(+PerViewBindingPoints::SHADOWS,
|
||||
engine.getDummyUniformBuffer(), 0, sizeof(ShadowUib));
|
||||
setSampler(+PerViewBindingPoints::STRUCTURE,
|
||||
engine.getZeroTexture(), {});
|
||||
setSampler(+PerViewBindingPoints::SHADOW_MAP,
|
||||
engine.getOneTextureArrayDepth(), {});
|
||||
setSampler(+PerViewBindingPoints::SSAO,
|
||||
engine.getZeroTextureArray(), {});
|
||||
setSampler(+PerViewBindingPoints::SSR,
|
||||
engine.getZeroTextureArray(), {});
|
||||
}
|
||||
|
||||
void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
|
||||
@@ -558,7 +560,7 @@ void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
|
||||
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
|
||||
auto samplers = mDescriptorSetLayout[i].getSamplerDescriptors();
|
||||
if (samplers[binding]) {
|
||||
mDescriptorSet[i].setSampler(binding, th, params);
|
||||
mDescriptorSet[i].setSampler(mDescriptorSetLayout[i], binding, th, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -566,9 +568,10 @@ void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
|
||||
void ColorPassDescriptorSet::setBuffer(descriptor_binding_t const binding,
|
||||
BufferObjectHandle boh, uint32_t const offset, uint32_t const size) noexcept {
|
||||
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
|
||||
auto ubos = mDescriptorSetLayout[i].getUniformBufferDescriptors();
|
||||
auto const& layout = mDescriptorSetLayout[i];
|
||||
auto ubos = layout.getUniformBufferDescriptors();
|
||||
if (ubos[binding]) {
|
||||
mDescriptorSet[i].setBuffer(binding, boh, offset, size);
|
||||
mDescriptorSet[i].setBuffer(layout, binding, boh, offset, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,16 +66,16 @@ class ColorPassDescriptorSet {
|
||||
using LightManagerInstance = utils::EntityInstance<LightManager>;
|
||||
using TextureHandle = backend::Handle<backend::HwTexture>;
|
||||
|
||||
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_PCF = 0u;
|
||||
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_EVSM = 1u;
|
||||
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_DPCF = 2u;
|
||||
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_PCSS = 3u;
|
||||
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_PCF = 0u;
|
||||
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_EVSM = 1u;
|
||||
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_DPCF = 2u;
|
||||
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_PCSS = 3u;
|
||||
|
||||
public:
|
||||
|
||||
static uint8_t getIndex(bool lit, bool ssr, bool fog) noexcept;
|
||||
|
||||
ColorPassDescriptorSet(FEngine& engine,
|
||||
ColorPassDescriptorSet(FEngine& engine, bool vsm,
|
||||
TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
|
||||
|
||||
void init(
|
||||
@@ -153,13 +153,15 @@ public:
|
||||
// update local data into GPU UBO
|
||||
void commit(backend::DriverApi& driver) noexcept;
|
||||
|
||||
void unbindSamplers(backend::DriverApi& driver) noexcept;
|
||||
void unbindSamplers(FEngine& engine) noexcept;
|
||||
|
||||
// bind this UBO
|
||||
void bind(backend::DriverApi& driver, uint8_t const index) const noexcept {
|
||||
mDescriptorSet[index].bind(driver, DescriptorSetBindingPoints::PER_VIEW);
|
||||
}
|
||||
|
||||
bool isVSM() const noexcept { return mIsVsm; }
|
||||
|
||||
private:
|
||||
static constexpr size_t DESCRIPTOR_LAYOUT_COUNT = 8;
|
||||
|
||||
@@ -169,11 +171,13 @@ private:
|
||||
void setBuffer(backend::descriptor_binding_t binding,
|
||||
backend::BufferObjectHandle boh, uint32_t offset, uint32_t size) noexcept;
|
||||
|
||||
static void prepareShadowSampling(PerViewUib& uniforms,
|
||||
ShadowMappingUniforms const& shadowMappingUniforms) noexcept;
|
||||
|
||||
TypedUniformBuffer<PerViewUib>& mUniforms;
|
||||
std::array<DescriptorSetLayout, DESCRIPTOR_LAYOUT_COUNT> mDescriptorSetLayout;
|
||||
std::array<DescriptorSet, DESCRIPTOR_LAYOUT_COUNT> mDescriptorSet;
|
||||
static void prepareShadowSampling(PerViewUib& uniforms,
|
||||
ShadowMappingUniforms const& shadowMappingUniforms) noexcept;
|
||||
bool const mIsVsm;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
@@ -86,6 +87,7 @@ void DescriptorSet::commitSlow(DescriptorSetLayout const& layout,
|
||||
mValid.forEachSetBit([&layout, &driver,
|
||||
dsh = mDescriptorSetHandle, descriptors = mDescriptors.data()]
|
||||
(backend::descriptor_binding_t const binding) {
|
||||
assert_invariant(layout.isValid(binding));
|
||||
if (layout.isSampler(binding)) {
|
||||
driver.updateDescriptorSetTexture(dsh, binding,
|
||||
descriptors[binding].texture.th,
|
||||
@@ -113,7 +115,7 @@ void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints
|
||||
// within the renderpass. We have to comment the assert out since it crashed a client's debug
|
||||
// build.
|
||||
// assert_invariant(mDirty.none());
|
||||
if (mDirty.any() && !mSetAfterCommitWarning) {
|
||||
if (UTILS_VERY_UNLIKELY(mDirty.any() && !mSetAfterCommitWarning)) {
|
||||
mDirty.forEachSetBit([&](uint8_t const binding) {
|
||||
utils::slog.w << "Descriptor set (handle=" << mDescriptorSetHandle.getId()
|
||||
<< ") binding=" << (int) binding
|
||||
@@ -124,35 +126,109 @@ void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints
|
||||
driver.bindDescriptorSet(mDescriptorSetHandle, +set, std::move(dynamicOffsets));
|
||||
}
|
||||
|
||||
void DescriptorSet::setBuffer(
|
||||
void DescriptorSet::setBuffer(DescriptorSetLayout const& layout,
|
||||
backend::descriptor_binding_t const binding,
|
||||
backend::Handle<backend::HwBufferObject> boh, uint32_t const offset, uint32_t const size) noexcept {
|
||||
// TODO: validate it's the right kind of descriptor
|
||||
backend::Handle<backend::HwBufferObject> boh, uint32_t const offset, uint32_t const size) {
|
||||
|
||||
// Validate it's the right kind of descriptor
|
||||
using DSLB = backend::DescriptorSetLayoutBinding;
|
||||
FILAMENT_CHECK_PRECONDITION(DSLB::isBuffer(layout.getDescriptorType(binding)))
|
||||
<< "descriptor " << +binding << "is not a buffer";
|
||||
|
||||
if (mDescriptors[binding].buffer.boh != boh || mDescriptors[binding].buffer.size != size) {
|
||||
// we don't set the dirty bit if only offset changes
|
||||
mDirty.set(binding);
|
||||
}
|
||||
mDescriptors[binding].buffer = { boh, offset, size };
|
||||
mValid.set(binding, (bool)boh);
|
||||
mValid.set(binding, bool(boh));
|
||||
}
|
||||
|
||||
void DescriptorSet::setSampler(
|
||||
DescriptorSetLayout const& layout,
|
||||
backend::descriptor_binding_t const binding,
|
||||
backend::Handle<backend::HwTexture> th, backend::SamplerParams const params) noexcept {
|
||||
// TODO: validate it's the right kind of descriptor
|
||||
backend::Handle<backend::HwTexture> th, backend::SamplerParams const params) {
|
||||
|
||||
using namespace backend;
|
||||
using DSLB = DescriptorSetLayoutBinding;
|
||||
|
||||
// Validate it's the right kind of descriptor
|
||||
auto type = layout.getDescriptorType(binding);
|
||||
FILAMENT_CHECK_PRECONDITION(DSLB::isSampler(type))
|
||||
<< "descriptor " << +binding << " is not a sampler";
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(
|
||||
!(params.compareMode == SamplerCompareMode::COMPARE_TO_TEXTURE && !isDepthDescriptor(type)))
|
||||
<< "descriptor " << +binding
|
||||
<< " is not of type DEPTH, but sampler is in COMPARE_TO_TEXTURE mode";
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(
|
||||
!(params.isFiltered() &&
|
||||
isDepthDescriptor(type) &&
|
||||
params.compareMode != SamplerCompareMode::COMPARE_TO_TEXTURE))
|
||||
<< "descriptor " << +binding
|
||||
<< " is of type filtered DEPTH, but sampler not in COMPARE_TO_TEXTURE mode";
|
||||
|
||||
if (mDescriptors[binding].texture.th != th || mDescriptors[binding].texture.params != params) {
|
||||
mDirty.set(binding);
|
||||
}
|
||||
mDescriptors[binding].texture = { th, params };
|
||||
mValid.set(binding, (bool)th);
|
||||
mValid.set(binding, bool(th));
|
||||
}
|
||||
|
||||
DescriptorSet DescriptorSet::duplicate(DescriptorSetLayout const& layout) const noexcept {
|
||||
DescriptorSet set{layout};
|
||||
set.mDescriptors = mDescriptors; // Use the vector's assignment operator
|
||||
set.mDirty = mDirty;
|
||||
set.mDirty = mValid | mDirty; // Dirty all valid descriptors so they're updated during commit
|
||||
set.mValid = mValid;
|
||||
return set;
|
||||
}
|
||||
bool DescriptorSet::isTextureCompatibleWithDescriptor(
|
||||
backend::TextureType t, backend::DescriptorType d) noexcept {
|
||||
using namespace backend;
|
||||
|
||||
switch (d) {
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
// DEPTH_STENCIL is treated as accessing the depth component. OpenGL 4.3
|
||||
// allows to specify which one, but not filament.
|
||||
// Depth textures can be used as an unfiltered float sampler
|
||||
return t == TextureType::FLOAT || t == TextureType::DEPTH || t == TextureType::DEPTH_STENCIL;
|
||||
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
return t == TextureType::INT;
|
||||
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_3D_UINT:
|
||||
return t == TextureType::UINT;
|
||||
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
// DEPTH_STENCIL is treated as accessing the depth component. OpenGL 4.3
|
||||
// allows to specify which one, but not filament.
|
||||
return t == TextureType::DEPTH || t == TextureType::DEPTH_STENCIL;
|
||||
|
||||
case DescriptorType::SAMPLER_EXTERNAL:
|
||||
case DescriptorType::UNIFORM_BUFFER:
|
||||
case DescriptorType::SHADER_STORAGE_BUFFER:
|
||||
case DescriptorType::INPUT_ATTACHMENT:
|
||||
return false;
|
||||
}
|
||||
|
||||
// should never happen
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -62,14 +62,16 @@ public:
|
||||
backend::DescriptorSetOffsetArray dynamicOffsets) const noexcept;
|
||||
|
||||
// sets a ubo/ssbo descriptor
|
||||
void setBuffer(backend::descriptor_binding_t binding,
|
||||
void setBuffer(DescriptorSetLayout const& layout,
|
||||
backend::descriptor_binding_t binding,
|
||||
backend::Handle<backend::HwBufferObject> boh,
|
||||
uint32_t offset, uint32_t size) noexcept;
|
||||
uint32_t offset, uint32_t size);
|
||||
|
||||
// sets a sampler descriptor
|
||||
void setSampler(backend::descriptor_binding_t binding,
|
||||
void setSampler(DescriptorSetLayout const& layout,
|
||||
backend::descriptor_binding_t binding,
|
||||
backend::Handle<backend::HwTexture> th,
|
||||
backend::SamplerParams params) noexcept;
|
||||
backend::SamplerParams params);
|
||||
|
||||
// Used for duplicating material
|
||||
DescriptorSet duplicate(DescriptorSetLayout const& layout) const noexcept;
|
||||
@@ -82,6 +84,9 @@ public:
|
||||
return mValid;
|
||||
}
|
||||
|
||||
static bool isTextureCompatibleWithDescriptor(
|
||||
backend::TextureType t, backend::DescriptorType d) noexcept;
|
||||
|
||||
private:
|
||||
struct Desc {
|
||||
Desc() noexcept { }
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
|
||||
#include "details/Engine.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -35,11 +38,15 @@ DescriptorSetLayout::DescriptorSetLayout(
|
||||
backend::DescriptorSetLayout descriptorSetLayout) noexcept {
|
||||
for (auto&& desc : descriptorSetLayout.bindings) {
|
||||
mMaxDescriptorBinding = std::max(mMaxDescriptorBinding, desc.binding);
|
||||
mSamplers.set(desc.binding,
|
||||
desc.type == backend::DescriptorType::SAMPLER ||
|
||||
desc.type == backend::DescriptorType::SAMPLER_EXTERNAL);
|
||||
mUniformBuffers.set(desc.binding,
|
||||
desc.type == backend::DescriptorType::UNIFORM_BUFFER);
|
||||
mSamplers.set(desc.binding, backend::DescriptorSetLayoutBinding::isSampler(desc.type));
|
||||
mUniformBuffers.set(desc.binding, desc.type == backend::DescriptorType::UNIFORM_BUFFER);
|
||||
}
|
||||
|
||||
assert_invariant(mMaxDescriptorBinding < utils::bitset64::BIT_COUNT);
|
||||
|
||||
mDescriptorTypes = utils::FixedCapacityVector<backend::DescriptorType>(mMaxDescriptorBinding + 1);
|
||||
for (auto&& desc : descriptorSetLayout.bindings) {
|
||||
mDescriptorTypes[desc.binding] = desc.type;
|
||||
}
|
||||
|
||||
mDescriptorSetLayoutHandle = factory.create(driver,
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@@ -56,6 +57,10 @@ public:
|
||||
return mMaxDescriptorBinding;
|
||||
}
|
||||
|
||||
bool isValid(backend::descriptor_binding_t const binding) const noexcept {
|
||||
return mSamplers[binding] || mUniformBuffers[binding];
|
||||
}
|
||||
|
||||
bool isSampler(backend::descriptor_binding_t const binding) const noexcept {
|
||||
return mSamplers[binding];
|
||||
}
|
||||
@@ -68,11 +73,17 @@ public:
|
||||
return mUniformBuffers;
|
||||
}
|
||||
|
||||
backend::DescriptorType getDescriptorType(
|
||||
backend::descriptor_binding_t const binding) const noexcept {
|
||||
return mDescriptorTypes[binding];
|
||||
}
|
||||
|
||||
private:
|
||||
backend::DescriptorSetLayoutHandle mDescriptorSetLayoutHandle;
|
||||
utils::bitset64 mSamplers;
|
||||
utils::bitset64 mUniformBuffers;
|
||||
uint8_t mMaxDescriptorBinding = 0;
|
||||
utils::FixedCapacityVector<backend::DescriptorType> mDescriptorTypes;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@ void PostProcessDescriptorSet::terminate(HwDescriptorSetLayoutFactory& factory,
|
||||
void PostProcessDescriptorSet::setFrameUniforms(DriverApi& driver,
|
||||
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
|
||||
// initialize the descriptor-set
|
||||
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
|
||||
mDescriptorSet.setBuffer(mDescriptorSetLayout,
|
||||
+PerViewBindingPoints::FRAME_UNIFORMS,
|
||||
uniforms.getUboHandle(), 0, uniforms.getSize());
|
||||
|
||||
mDescriptorSet.commit(mDescriptorSetLayout, driver);
|
||||
|
||||
@@ -46,8 +46,8 @@ ShadowMapDescriptorSet::ShadowMapDescriptorSet(FEngine& engine) noexcept {
|
||||
mDescriptorSet = DescriptorSet{ engine.getPerViewDescriptorSetLayoutDepthVariant() };
|
||||
|
||||
// initialize the descriptor-set
|
||||
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
|
||||
mUniformBufferHandle, 0, sizeof(PerViewUib));
|
||||
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutDepthVariant(),
|
||||
+PerViewBindingPoints::FRAME_UNIFORMS, mUniformBufferHandle, 0, sizeof(PerViewUib));
|
||||
}
|
||||
|
||||
void ShadowMapDescriptorSet::terminate(DriverApi& driver) {
|
||||
|
||||
@@ -53,28 +53,32 @@ void SsrPassDescriptorSet::terminate(DriverApi& driver) {
|
||||
driver.destroyBufferObject(mShadowUbh);
|
||||
}
|
||||
|
||||
void SsrPassDescriptorSet::setFrameUniforms(TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
|
||||
void SsrPassDescriptorSet::setFrameUniforms(FEngine const& engine,
|
||||
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
|
||||
// initialize the descriptor-set
|
||||
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
|
||||
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutSsrVariant(),
|
||||
+PerViewBindingPoints::FRAME_UNIFORMS,
|
||||
uniforms.getUboHandle(), 0, uniforms.getSize());
|
||||
|
||||
// This is actually not used for the SSR variants, but the descriptor-set layout needs
|
||||
// to have this UBO because the fragment shader used is the "generic" one. Both Metal
|
||||
// and GL would be okay without this, but Vulkan's validation layer would complain.
|
||||
mDescriptorSet.setBuffer(+PerViewBindingPoints::SHADOWS, mShadowUbh, 0, sizeof(ShadowUib));
|
||||
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutSsrVariant(),
|
||||
+PerViewBindingPoints::SHADOWS, mShadowUbh, 0, sizeof(ShadowUib));
|
||||
|
||||
mUniforms = std::addressof(uniforms);
|
||||
}
|
||||
|
||||
void SsrPassDescriptorSet::prepareHistorySSR(Handle<HwTexture> ssr,
|
||||
void SsrPassDescriptorSet::prepareHistorySSR(FEngine const& engine, Handle<HwTexture> ssr,
|
||||
mat4f const& historyProjection,
|
||||
mat4f const& uvFromViewMatrix,
|
||||
ScreenSpaceReflectionsOptions const& ssrOptions) noexcept {
|
||||
|
||||
mDescriptorSet.setSampler(+PerViewBindingPoints::SSR, ssr, {
|
||||
.filterMag = SamplerMagFilter::LINEAR,
|
||||
.filterMin = SamplerMinFilter::LINEAR
|
||||
});
|
||||
mDescriptorSet.setSampler(engine.getPerViewDescriptorSetLayoutSsrVariant(),
|
||||
+PerViewBindingPoints::SSR, ssr, {
|
||||
.filterMag = SamplerMagFilter::LINEAR,
|
||||
.filterMin = SamplerMinFilter::LINEAR
|
||||
});
|
||||
|
||||
assert_invariant(mUniforms);
|
||||
auto& s = mUniforms->edit();
|
||||
@@ -86,9 +90,11 @@ void SsrPassDescriptorSet::prepareHistorySSR(Handle<HwTexture> ssr,
|
||||
s.ssrStride = ssrOptions.stride;
|
||||
}
|
||||
|
||||
void SsrPassDescriptorSet::prepareStructure(Handle<HwTexture> structure) noexcept {
|
||||
void SsrPassDescriptorSet::prepareStructure(FEngine const& engine,
|
||||
Handle<HwTexture> structure) noexcept {
|
||||
// sampler must be NEAREST
|
||||
mDescriptorSet.setSampler(+PerViewBindingPoints::STRUCTURE, structure, {});
|
||||
mDescriptorSet.setSampler(engine.getPerViewDescriptorSetLayoutSsrVariant(),
|
||||
+PerViewBindingPoints::STRUCTURE, structure, {});
|
||||
}
|
||||
|
||||
void SsrPassDescriptorSet::commit(FEngine& engine) noexcept {
|
||||
|
||||
@@ -47,11 +47,11 @@ public:
|
||||
|
||||
void terminate(backend::DriverApi& driver);
|
||||
|
||||
void setFrameUniforms(TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
|
||||
void setFrameUniforms(FEngine const& engine, TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
|
||||
|
||||
void prepareStructure(TextureHandle structure) noexcept;
|
||||
void prepareStructure(FEngine const& engine, TextureHandle structure) noexcept;
|
||||
|
||||
void prepareHistorySSR(TextureHandle ssr,
|
||||
void prepareHistorySSR(FEngine const& engine, TextureHandle ssr,
|
||||
math::mat4f const& historyProjection,
|
||||
math::mat4f const& uvFromViewMatrix,
|
||||
ScreenSpaceReflectionsOptions const& ssrOptions) noexcept;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.60.1"
|
||||
spec.version = "1.59.5"
|
||||
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.60.1/filament-v1.60.1-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.5/filament-v1.59.5-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -35,23 +35,20 @@ backend::DescriptorSetLayout const& getPerRenderableLayout() noexcept;
|
||||
|
||||
backend::DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
MaterialDomain domain,
|
||||
UserVariantFilterMask variantFilter,
|
||||
bool isLit,
|
||||
ReflectionMode reflectionMode,
|
||||
RefractionMode refractionMode) noexcept;
|
||||
bool isLit, bool isSSR, bool hasFog,
|
||||
bool isVSM) noexcept;
|
||||
|
||||
backend::DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
|
||||
Variant variant,
|
||||
MaterialDomain domain,
|
||||
UserVariantFilterMask variantFilter,
|
||||
bool isLit,
|
||||
ReflectionMode reflectionMode,
|
||||
RefractionMode refractionMode) noexcept;
|
||||
bool isLit, bool isSSR, bool hasFog) noexcept;
|
||||
|
||||
utils::CString getDescriptorName(
|
||||
DescriptorSetBindingPoints set,
|
||||
backend::descriptor_binding_t binding) noexcept;
|
||||
|
||||
backend::DescriptorType getDescriptorType(backend::SamplerType type, backend::SamplerFormat format);
|
||||
|
||||
} // namespace filament::descriptor_sets
|
||||
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ public:
|
||||
using Precision = backend::Precision;
|
||||
using SamplerParams = backend::SamplerParams;
|
||||
using Binding = backend::descriptor_binding_t;
|
||||
using ShaderStageFlags = backend::ShaderStageFlags;
|
||||
|
||||
struct SamplerInfo { // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
utils::CString name; // name of this sampler
|
||||
@@ -62,7 +61,6 @@ public:
|
||||
Format format; // format of this sampler
|
||||
Precision precision; // precision of this sampler
|
||||
bool multisample; // multisample capable
|
||||
ShaderStageFlags stages; // stages the sampler can be accessed from
|
||||
};
|
||||
|
||||
using SamplerInfoList = utils::FixedCapacityVector<SamplerInfo>;
|
||||
@@ -84,8 +82,6 @@ public:
|
||||
Format format; // format of this sampler
|
||||
Precision precision; // precision of this sampler
|
||||
bool multisample = false; // multisample capable
|
||||
ShaderStageFlags stages =
|
||||
ShaderStageFlags::ALL_SHADER_STAGE_FLAGS; // shader stages using this sampler
|
||||
};
|
||||
|
||||
// Give a name to this sampler interface block
|
||||
@@ -95,8 +91,8 @@ public:
|
||||
|
||||
// Add a sampler
|
||||
Builder& add(std::string_view samplerName, Binding binding, Type type, Format format,
|
||||
Precision precision = Precision::MEDIUM, bool multisample = false,
|
||||
ShaderStageFlags stages = ShaderStageFlags::ALL_SHADER_STAGE_FLAGS) noexcept;
|
||||
Precision precision = Precision::MEDIUM,
|
||||
bool multisample = false) noexcept;
|
||||
|
||||
// Add multiple samplers
|
||||
Builder& add(std::initializer_list<ListEntry> list) noexcept;
|
||||
|
||||
@@ -24,21 +24,28 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/CString.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/StaticString.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
namespace filament::descriptor_sets {
|
||||
|
||||
using namespace backend;
|
||||
|
||||
// used for post-processing passes
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> postProcessDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
};
|
||||
|
||||
// used to generate shadow-maps
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> depthVariantDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
};
|
||||
@@ -51,32 +58,88 @@ static constexpr std::initializer_list<DescriptorSetLayoutBinding> depthVariantD
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> ssrVariantDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
|
||||
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
|
||||
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
|
||||
};
|
||||
|
||||
// Used for generating the color pass (i.e. the main pass). This is in fact a template that gets
|
||||
// declined into 8 different layouts, based on variants.
|
||||
//
|
||||
// Note about the SHADOW_MAP binding points:
|
||||
// This descriptor can either be a SAMPLER_FLOAT or a SAMPLER_DEPTH,
|
||||
// and there are 3 cases to consider:
|
||||
//
|
||||
// | TextureType | CompareMode | Filtered | SamplerType | Variant |
|
||||
// ---------+-------------+-------------+----------+-------------+---------+
|
||||
// PCF | DEPTH | COMPARE | Yes | DEPTH | - |
|
||||
// VSM | FLOAT | NONE | Yes | FLOAT | VSM |
|
||||
// OTHER | DEPTH | NONE | No | FLOAT | VSM |
|
||||
//
|
||||
// The SamplerType to use depends on the Variant. Variant::VSM is set for all cases except PCM.
|
||||
//
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> perViewDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::LIGHTS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::RECORD_BUFFER },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FROXEL_BUFFER },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOW_MAP },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_DFG_LUT },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_SPECULAR },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSAO },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
|
||||
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
|
||||
{ DescriptorType::SAMPLER_2D_ARRAY_DEPTH, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOW_MAP },
|
||||
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_DFG_LUT },
|
||||
{ DescriptorType::SAMPLER_CUBE_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_SPECULAR },
|
||||
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSAO },
|
||||
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
|
||||
{ DescriptorType::SAMPLER_CUBE_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
|
||||
};
|
||||
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> perRenderableDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::OBJECT_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::BONES_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::MORPHING_UNIFORMS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_POSITIONS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_TANGENTS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::OBJECT_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::BONES_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::MORPHING_UNIFORMS },
|
||||
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_POSITIONS },
|
||||
{ DescriptorType::SAMPLER_2D_ARRAY_INT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_TANGENTS },
|
||||
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS },
|
||||
};
|
||||
|
||||
struct PairSamplerTypeFormatHasher {
|
||||
std::size_t operator()(const std::pair<SamplerType, SamplerFormat>& p) const {
|
||||
using UnderlyingSamplerType = std::underlying_type_t<SamplerType>;
|
||||
using UnderlyingSamplerFormat = std::underlying_type_t<SamplerFormat>;
|
||||
std::size_t seed = 0;
|
||||
std::size_t const hash1 = std::hash<UnderlyingSamplerType>{}(
|
||||
static_cast<UnderlyingSamplerType>(p.first)
|
||||
);
|
||||
std::size_t const hash2 = std::hash<UnderlyingSamplerFormat>{}(
|
||||
static_cast<UnderlyingSamplerFormat>(p.second)
|
||||
);
|
||||
seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
static const std::unordered_map<
|
||||
std::pair<SamplerType, SamplerFormat>, DescriptorType, PairSamplerTypeFormatHasher> sDescriptorTypeMap{
|
||||
{{ SamplerType::SAMPLER_2D, SamplerFormat::INT }, DescriptorType::SAMPLER_2D_INT },
|
||||
{{ SamplerType::SAMPLER_2D, SamplerFormat::UINT }, DescriptorType::SAMPLER_2D_UINT },
|
||||
{{ SamplerType::SAMPLER_2D, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_2D_FLOAT },
|
||||
{{ SamplerType::SAMPLER_2D, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_2D_DEPTH },
|
||||
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::INT }, DescriptorType::SAMPLER_2D_ARRAY_INT },
|
||||
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::UINT }, DescriptorType::SAMPLER_2D_ARRAY_UINT },
|
||||
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_2D_ARRAY_FLOAT },
|
||||
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_2D_ARRAY_DEPTH },
|
||||
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::INT }, DescriptorType::SAMPLER_CUBE_INT },
|
||||
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::UINT }, DescriptorType::SAMPLER_CUBE_UINT },
|
||||
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_CUBE_FLOAT },
|
||||
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_CUBE_DEPTH },
|
||||
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::INT }, DescriptorType::SAMPLER_CUBE_ARRAY_INT },
|
||||
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::UINT }, DescriptorType::SAMPLER_CUBE_ARRAY_UINT },
|
||||
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT },
|
||||
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH },
|
||||
{{ SamplerType::SAMPLER_3D, SamplerFormat::INT }, DescriptorType::SAMPLER_3D_INT },
|
||||
{{ SamplerType::SAMPLER_3D, SamplerFormat::UINT }, DescriptorType::SAMPLER_3D_UINT },
|
||||
{{ SamplerType::SAMPLER_3D, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_3D_FLOAT },
|
||||
{{ SamplerType::SAMPLER_EXTERNAL, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_EXTERNAL }
|
||||
};
|
||||
|
||||
// used for post-processing passes
|
||||
@@ -146,12 +209,12 @@ utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
|
||||
|
||||
switch (set) {
|
||||
case DescriptorSetBindingPoints::PER_VIEW: {
|
||||
auto pos = set0.find(binding);
|
||||
auto const pos = set0.find(binding);
|
||||
assert_invariant(pos != set0.end());
|
||||
return { pos->second.data(), pos->second.size() };
|
||||
}
|
||||
case DescriptorSetBindingPoints::PER_RENDERABLE: {
|
||||
auto pos = set1.find(binding);
|
||||
auto const pos = set1.find(binding);
|
||||
assert_invariant(pos != set1.end());
|
||||
return { pos->second.data(), pos->second.size() };
|
||||
}
|
||||
@@ -160,17 +223,13 @@ utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
|
||||
return "MaterialParams";
|
||||
}
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
MaterialDomain const domain,
|
||||
UserVariantFilterMask const variantFilter,
|
||||
bool const isLit,
|
||||
ReflectionMode const reflectionMode,
|
||||
RefractionMode const refractionMode) noexcept {
|
||||
|
||||
bool const ssr = reflectionMode == ReflectionMode::SCREEN_SPACE ||
|
||||
refractionMode == RefractionMode::SCREEN_SPACE;
|
||||
bool const isLit, bool const isSSR, bool const hasFog,
|
||||
bool const isVSM) noexcept {
|
||||
|
||||
switch (domain) {
|
||||
case MaterialDomain::SURFACE: {
|
||||
@@ -189,7 +248,7 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
layout.bindings.end());
|
||||
}
|
||||
// remove descriptors not needed for SSRs
|
||||
if (!ssr) {
|
||||
if (!isSSR) {
|
||||
layout.bindings.erase(
|
||||
std::remove_if(layout.bindings.begin(), layout.bindings.end(),
|
||||
[](auto const& entry) {
|
||||
@@ -199,7 +258,7 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
|
||||
}
|
||||
// remove fog descriptor if filtered out
|
||||
if (variantFilter & (UserVariantFilterMask)UserVariantFilterBit::FOG) {
|
||||
if (!hasFog) {
|
||||
layout.bindings.erase(
|
||||
std::remove_if(layout.bindings.begin(), layout.bindings.end(),
|
||||
[](auto const& entry) {
|
||||
@@ -207,6 +266,17 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
}),
|
||||
layout.bindings.end());
|
||||
}
|
||||
|
||||
// change the SHADOW_MAP descriptor type for VSM
|
||||
if (isVSM) {
|
||||
auto const pos = std::find_if(layout.bindings.begin(), layout.bindings.end(),
|
||||
[](auto const& v) {
|
||||
return v.binding == PerViewBindingPoints::SHADOW_MAP;
|
||||
});
|
||||
if (pos != layout.bindings.end()) {
|
||||
pos->type = DescriptorType::SAMPLER_2D_ARRAY_FLOAT;
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
case MaterialDomain::POST_PROCESS:
|
||||
@@ -219,11 +289,8 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
|
||||
DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
|
||||
Variant const variant,
|
||||
MaterialDomain domain,
|
||||
UserVariantFilterMask const variantFilter,
|
||||
bool const isLit,
|
||||
ReflectionMode const reflectionMode,
|
||||
RefractionMode const refractionMode) noexcept {
|
||||
MaterialDomain const domain,
|
||||
bool const isLit, bool const isSSR, bool const hasFog) noexcept {
|
||||
if (Variant::isValidDepthVariant(variant)) {
|
||||
return depthVariantDescriptorSetLayout;
|
||||
}
|
||||
@@ -231,11 +298,17 @@ DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
|
||||
return ssrVariantDescriptorSetLayout;
|
||||
}
|
||||
// We need to filter out all the descriptors not included in the "resolved" layout below
|
||||
return getPerViewDescriptorSetLayout(domain, variantFilter,
|
||||
isLit, reflectionMode, refractionMode);
|
||||
return getPerViewDescriptorSetLayout(domain, isLit, isSSR, hasFog,
|
||||
Variant::isVSMVariant(variant));
|
||||
}
|
||||
|
||||
|
||||
DescriptorType getDescriptorType(SamplerType const type, SamplerFormat const format) {
|
||||
auto const pos = sDescriptorTypeMap.find({ type, format });
|
||||
FILAMENT_CHECK_PRECONDITION(pos != sDescriptorTypeMap.end())
|
||||
<< "Incompatible Sampler Format " << to_string(format)
|
||||
<< " and Type " << to_string(type);
|
||||
return pos->second;
|
||||
}
|
||||
|
||||
template<class ITERATOR, class PREDICATE>
|
||||
constexpr static ITERATOR find_if(ITERATOR first, ITERATOR last, PREDICATE pred) {
|
||||
|
||||
@@ -49,13 +49,13 @@ SamplerInterfaceBlock::Builder::stageFlags(backend::ShaderStageFlags stageFlags)
|
||||
return *this;
|
||||
}
|
||||
|
||||
SamplerInterfaceBlock::Builder& SamplerInterfaceBlock::Builder::add(std::string_view samplerName,
|
||||
Binding binding, Type type, Format format, Precision precision, bool multisample,
|
||||
ShaderStageFlags stages) noexcept {
|
||||
SamplerInterfaceBlock::Builder& SamplerInterfaceBlock::Builder::add(
|
||||
std::string_view samplerName, Binding binding, Type type, Format format,
|
||||
Precision precision, bool multisample) noexcept {
|
||||
mEntries.push_back({
|
||||
{ samplerName.data(), samplerName.size() }, // name
|
||||
{ }, // uniform name
|
||||
binding, type, format, precision, multisample, stages });
|
||||
binding, type, format, precision, multisample });
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ SamplerInterfaceBlock SamplerInterfaceBlock::Builder::build() {
|
||||
SamplerInterfaceBlock::Builder& SamplerInterfaceBlock::Builder::add(
|
||||
std::initializer_list<ListEntry> list) noexcept {
|
||||
for (auto& e : list) {
|
||||
add(e.name, e.binding, e.type, e.format, e.precision, e.multisample, e.stages);
|
||||
add(e.name, e.binding, e.type, e.format, e.precision, e.multisample);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -91,7 +91,6 @@ SamplerInterfaceBlock::SamplerInterfaceBlock(Builder const& builder) noexcept
|
||||
size_t const i = std::distance(builder.mEntries.data(), &e);
|
||||
SamplerInfo& info = samplersInfoList[i];
|
||||
info = e;
|
||||
info.stages &= builder.mStageFlags;
|
||||
info.uniformName = generateUniformName(mName.c_str(), e.name.c_str());
|
||||
infoMap[{ info.name.data(), info.name.size() }] = i; // info.name.c_str() guaranteed constant
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ set(PRIVATE_HDRS
|
||||
src/MetalArgumentBuffer.h
|
||||
src/ShaderMinifier.h
|
||||
src/SpirvFixup.h
|
||||
src/SpirvRemapWrapper.h
|
||||
src/sca/ASTHelpers.h
|
||||
src/sca/GLSLTools.h
|
||||
src/sca/builtinResource.h)
|
||||
@@ -72,8 +71,7 @@ set(SRCS
|
||||
src/sca/GLSLTools.cpp
|
||||
src/GLSLPostProcessor.cpp
|
||||
src/ShaderMinifier.cpp
|
||||
src/SpirvFixup.cpp
|
||||
src/SpirvRemapWrapper.cpp)
|
||||
src/SpirvFixup.cpp)
|
||||
|
||||
# ==================================================================================================
|
||||
# Include and target definitions
|
||||
|
||||
@@ -35,7 +35,6 @@ using OutputTarget = MaterialBuilder::OutputTarget;
|
||||
using OutputQualifier = MaterialBuilder::VariableQualifier;
|
||||
using OutputType = MaterialBuilder::OutputType;
|
||||
using ConstantType = MaterialBuilder::ConstantType;
|
||||
using ShaderStageType = MaterialBuilder::ShaderStageFlags;
|
||||
|
||||
// Convenience methods to convert std::string to Enum and also iterate over Enum values.
|
||||
class Enums {
|
||||
@@ -80,7 +79,6 @@ private:
|
||||
static std::unordered_map<std::string, OutputQualifier> mStringToOutputQualifier;
|
||||
static std::unordered_map<std::string, OutputType> mStringToOutputType;
|
||||
static std::unordered_map<std::string, ConstantType> mStringToConstantType;
|
||||
static std::unordered_map<std::string, ShaderStageType> mStringToShaderStageType;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -254,7 +254,6 @@ public:
|
||||
using FeatureLevel = filament::backend::FeatureLevel;
|
||||
using StereoscopicType = filament::backend::StereoscopicType;
|
||||
using ShaderStage = filament::backend::ShaderStage;
|
||||
using ShaderStageFlags = filament::backend::ShaderStageFlags;
|
||||
|
||||
enum class VariableQualifier : uint8_t {
|
||||
OUT
|
||||
@@ -323,9 +322,9 @@ public:
|
||||
*/
|
||||
MaterialBuilder& parameter(const char* name, SamplerType samplerType,
|
||||
SamplerFormat format = SamplerFormat::FLOAT,
|
||||
ParameterPrecision precision = ParameterPrecision::DEFAULT, bool multisample = false,
|
||||
const char* transformName = "",
|
||||
ShaderStageFlags stages = ShaderStageFlags::ALL_SHADER_STAGE_FLAGS) noexcept;
|
||||
ParameterPrecision precision = ParameterPrecision::DEFAULT,
|
||||
bool multisample = false,
|
||||
const char* transformName = "") noexcept;
|
||||
|
||||
MaterialBuilder& buffer(filament::BufferInterfaceBlock bib) noexcept;
|
||||
|
||||
@@ -657,10 +656,8 @@ public:
|
||||
Parameter() noexcept: parameterType(INVALID) {}
|
||||
|
||||
// Sampler
|
||||
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p,
|
||||
bool ms, const char* tn, ShaderStageFlags s)
|
||||
: name(paramName), size(1), precision(p), samplerType(t), format(f),
|
||||
parameterType(SAMPLER), multisample(ms), transformName(tn), stages(s) { }
|
||||
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p, bool ms, const char* tn)
|
||||
: name(paramName), size(1), precision(p), samplerType(t), format(f), parameterType(SAMPLER), multisample(ms), transformName(tn) { }
|
||||
|
||||
// Uniform
|
||||
Parameter(const char* paramName, UniformType t, size_t typeSize, ParameterPrecision p)
|
||||
@@ -679,7 +676,6 @@ public:
|
||||
SamplerFormat format;
|
||||
bool multisample;
|
||||
utils::CString transformName;
|
||||
ShaderStageFlags stages;
|
||||
enum {
|
||||
INVALID,
|
||||
UNIFORM,
|
||||
|
||||
@@ -175,15 +175,4 @@ std::unordered_map<std::string, ConstantType>& Enums::getMap<ConstantType>() noe
|
||||
return mStringToConstantType;
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, ShaderStageType> Enums::mStringToShaderStageType = {
|
||||
{ "fragment", ShaderStageType::FRAGMENT },
|
||||
{ "vertex", ShaderStageType::VERTEX },
|
||||
{ "compute", ShaderStageType::COMPUTE },
|
||||
};
|
||||
|
||||
template <>
|
||||
std::unordered_map<std::string, ShaderStageType>& Enums::getMap<ShaderStageType>() noexcept {
|
||||
return mStringToShaderStageType;
|
||||
};
|
||||
|
||||
} // namespace filamat
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
#include "GLSLPostProcessor.h"
|
||||
|
||||
#include <GlslangToSpv.h>
|
||||
#include <SPVRemapper.h>
|
||||
#include <spirv-tools/libspirv.hpp>
|
||||
|
||||
#include <spirv_glsl.hpp>
|
||||
#include <spirv_msl.hpp>
|
||||
|
||||
#include "backend/DriverEnums.h"
|
||||
#include "private/filament/DescriptorSets.h"
|
||||
#include "sca/builtinResource.h"
|
||||
#include "sca/GLSLTools.h"
|
||||
@@ -44,10 +44,15 @@
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef FILAMENT_SUPPORTS_WEBGPU
|
||||
#include <tint/tint.h>
|
||||
#endif
|
||||
@@ -70,22 +75,7 @@ using BindingIndexMap = std::unordered_map<std::string, uint16_t>;
|
||||
#define DEBUG_LOG_DESCRIPTOR_SETS 0
|
||||
#endif
|
||||
|
||||
const char* toString(DescriptorType type) {
|
||||
switch (type) {
|
||||
case DescriptorType::UNIFORM_BUFFER:
|
||||
return "UNIFORM_BUFFER";
|
||||
case DescriptorType::SHADER_STORAGE_BUFFER:
|
||||
return "SHADER_STORAGE_BUFFER";
|
||||
case DescriptorType::SAMPLER:
|
||||
return "SAMPLER";
|
||||
case DescriptorType::INPUT_ATTACHMENT:
|
||||
return "INPUT_ATTACHMENT";
|
||||
case DescriptorType::SAMPLER_EXTERNAL:
|
||||
return "SAMPLER_EXTERNAL";
|
||||
}
|
||||
}
|
||||
|
||||
const char* toString(ShaderStageFlags flags) {
|
||||
static const char* toString(ShaderStageFlags const flags) {
|
||||
std::vector<const char*> stages;
|
||||
if (any(flags & ShaderStageFlags::VERTEX)) {
|
||||
stages.push_back("VERTEX");
|
||||
@@ -110,14 +100,14 @@ const char* toString(ShaderStageFlags flags) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char* prettyDescriptorFlags(DescriptorFlags flags) {
|
||||
static const char* prettyDescriptorFlags(DescriptorFlags const flags) {
|
||||
if (flags == DescriptorFlags::DYNAMIC_OFFSET) {
|
||||
return "DYNAMIC_OFFSET";
|
||||
}
|
||||
return "NONE";
|
||||
}
|
||||
|
||||
const char* prettyPrintSamplerType(SamplerType type) {
|
||||
static const char* prettyPrintSamplerType(SamplerType const type) {
|
||||
switch (type) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
return "SAMPLER_2D";
|
||||
@@ -145,11 +135,17 @@ DescriptorSetLayout getPerMaterialDescriptorSet(SamplerInterfaceBlock const& sib
|
||||
+PerMaterialBindingPoints::MATERIAL_PARAMS, DescriptorFlags::NONE, 0 });
|
||||
|
||||
for (auto const& sampler: samplers) {
|
||||
layout.bindings.push_back(DescriptorSetLayoutBinding{
|
||||
(sampler.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL)
|
||||
? DescriptorType::SAMPLER_EXTERNAL
|
||||
: DescriptorType::SAMPLER,
|
||||
sampler.stages, sampler.binding, DescriptorFlags::NONE, 0 });
|
||||
DescriptorSetLayoutBinding layoutBinding{
|
||||
DescriptorType::SAMPLER_EXTERNAL,
|
||||
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
|
||||
sampler.binding,
|
||||
DescriptorFlags::NONE,
|
||||
0
|
||||
};
|
||||
if (sampler.type != SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
|
||||
layoutBinding.type = descriptor_sets::getDescriptorType(sampler.type, sampler.format);
|
||||
}
|
||||
layout.bindings.push_back(layoutBinding);
|
||||
}
|
||||
|
||||
return layout;
|
||||
@@ -163,11 +159,12 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
|
||||
DescriptorSetLayout const descriptorSetLayout = [&] {
|
||||
switch (set) {
|
||||
case DescriptorSetBindingPoints::PER_VIEW: {
|
||||
bool const isLit = material.isLit || material.hasShadowMultiplier;
|
||||
bool const isSSR = material.reflectionMode == ReflectionMode::SCREEN_SPACE ||
|
||||
material.refractionMode == RefractionMode::SCREEN_SPACE;
|
||||
bool const hasFog = !(config.variantFilter & UserVariantFilterMask(UserVariantFilterBit::FOG));
|
||||
return descriptor_sets::getPerViewDescriptorSetLayoutWithVariant(
|
||||
config.variant, config.domain, config.variantFilter,
|
||||
material.isLit || material.hasShadowMultiplier,
|
||||
material.reflectionMode,
|
||||
material.refractionMode);
|
||||
config.variant, config.domain, isLit, isSSR, hasFog);
|
||||
}
|
||||
case DescriptorSetBindingPoints::PER_RENDERABLE:
|
||||
return descriptor_sets::getPerRenderableLayout();
|
||||
@@ -209,17 +206,16 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
|
||||
return descriptor_sets::getDescriptorName(set, binding);
|
||||
};
|
||||
|
||||
for (auto descriptor : descriptorSetLayout.bindings) {
|
||||
descriptor_binding_t binding = descriptor.binding;
|
||||
for (auto const& layoutBinding : descriptorSetLayout.bindings) {
|
||||
descriptor_binding_t binding = layoutBinding.binding;
|
||||
auto name = getDescriptorName(binding);
|
||||
if (descriptor.type == DescriptorType::SAMPLER ||
|
||||
descriptor.type == DescriptorType::SAMPLER_EXTERNAL) {
|
||||
auto pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
|
||||
if (DescriptorSetLayoutBinding::isSampler(layoutBinding.type)) {
|
||||
auto const pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
|
||||
[&](const auto& entry) { return entry.binding == binding; });
|
||||
assert_invariant(pos != descriptorSetSamplerList.end());
|
||||
descriptors.emplace_back(name, descriptor, *pos);
|
||||
descriptors.emplace_back(name, layoutBinding, *pos);
|
||||
} else {
|
||||
descriptors.emplace_back(name, descriptor, std::nullopt);
|
||||
descriptors.emplace_back(name, layoutBinding, std::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,8 +224,8 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
|
||||
});
|
||||
}
|
||||
|
||||
void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) {
|
||||
auto getName = [](uint8_t set) {
|
||||
static void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) noexcept {
|
||||
auto getName = [](uint8_t const set) {
|
||||
switch (set) {
|
||||
case +DescriptorSetBindingPoints::PER_VIEW:
|
||||
return "perViewDescriptorSetLayout";
|
||||
@@ -246,18 +242,23 @@ void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) {
|
||||
printf("[DS] info (%s) = [\n", getName(setIndex));
|
||||
for (auto const& descriptor : descriptors) {
|
||||
auto const& [name, info, sampler] = descriptor;
|
||||
if (info.type == DescriptorType::SAMPLER ||
|
||||
info.type == DescriptorType::SAMPLER_EXTERNAL) {
|
||||
if (DescriptorSetLayoutBinding::isSampler(info.type)) {
|
||||
assert_invariant(sampler.has_value());
|
||||
printf(" {name = %s, binding = %d, type = %s, count = %d, stage = %s, flags = "
|
||||
printf(" {name = %s, binding = %d, type = %.*s, count = %d, stage = %s, flags = "
|
||||
"%s, samplerType = %s}",
|
||||
name.c_str_safe(), info.binding, toString(info.type), info.count,
|
||||
name.c_str_safe(), info.binding,
|
||||
int(to_string(info.type).size()),
|
||||
to_string(info.type).data(),
|
||||
info.count,
|
||||
toString(info.stageFlags), prettyDescriptorFlags(info.flags),
|
||||
prettyPrintSamplerType(sampler->type));
|
||||
} else {
|
||||
printf(" {name = %s, binding = %d, type = %s, count = %d, stage = %s, flags = "
|
||||
printf(" {name = %s, binding = %d, type = %.*s, count = %d, stage = %s, flags = "
|
||||
"%s}",
|
||||
name.c_str_safe(), info.binding, toString(info.type), info.count,
|
||||
name.c_str_safe(), info.binding,
|
||||
int(to_string(info.type).size()),
|
||||
to_string(info.type).data(),
|
||||
info.count,
|
||||
toString(info.stageFlags), prettyDescriptorFlags(info.flags));
|
||||
}
|
||||
printf(",\n");
|
||||
@@ -288,8 +289,24 @@ GLSLPostProcessor::GLSLPostProcessor(MaterialBuilder::Optimization optimization,
|
||||
: mOptimization(optimization),
|
||||
mPrintShaders(flags & PRINT_SHADERS),
|
||||
mGenerateDebugInfo(flags & GENERATE_DEBUG_INFO) {
|
||||
// This should occur only once, to avoid races.
|
||||
SpirvRemapWrapperSetUp();
|
||||
// SPIRV error handler registration needs to occur only once. To avoid a race we do it up here
|
||||
// in the constructor, which gets invoked before MaterialBuilder kicks off jobs.
|
||||
spv::spirvbin_t::registerErrorHandler([](const std::string& str) {
|
||||
slog.e << str << io::endl;
|
||||
});
|
||||
|
||||
// Similar to above, we need to do a no-op remap to init a static table in the remapper before
|
||||
// the jobs start using remap().
|
||||
spv::spirvbin_t remapper(0);
|
||||
// We need to provide at least a valid header to not crash.
|
||||
SpirvBlob spirv {
|
||||
0x07230203,// MAGIC
|
||||
0, // VERSION
|
||||
0, // GENERATOR
|
||||
0, // BOUND
|
||||
0 // SCHEMA, must be 0
|
||||
};
|
||||
remapper.remap(spirv, 0);
|
||||
}
|
||||
|
||||
GLSLPostProcessor::~GLSLPostProcessor() = default;
|
||||
@@ -455,7 +472,25 @@ void GLSLPostProcessor::spirvToMsl(const SpirvBlob* spirv, std::string* outMsl,
|
||||
break;
|
||||
}
|
||||
|
||||
case DescriptorType::SAMPLER:
|
||||
case DescriptorType::SAMPLER_2D_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_INT:
|
||||
case DescriptorType::SAMPLER_2D_UINT:
|
||||
case DescriptorType::SAMPLER_2D_DEPTH:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_DEPTH:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
|
||||
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
|
||||
case DescriptorType::SAMPLER_3D_FLOAT:
|
||||
case DescriptorType::SAMPLER_3D_INT:
|
||||
case DescriptorType::SAMPLER_3D_UINT:
|
||||
case DescriptorType::SAMPLER_EXTERNAL: {
|
||||
assert_invariant(sampler.has_value());
|
||||
const std::string samplerName = std::string(name.c_str()) + "Smplr";
|
||||
@@ -551,7 +586,7 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
|
||||
//After splitting the image samplers, we need to remap the bindings to separate them.
|
||||
rebindImageSamplerForWGSL(*spirv);
|
||||
|
||||
//Allow non-uniform derivitives due to our nested shaders. See https://github.com/gpuweb/gpuweb/issues/3479
|
||||
//Allow non-uniform derivatives due to our nested shaders. See https://github.com/gpuweb/gpuweb/issues/3479
|
||||
const tint::spirv::reader::Options readerOpts{true};
|
||||
tint::wgsl::writer::Options writerOpts{};
|
||||
|
||||
@@ -590,7 +625,9 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
|
||||
*outWsl = wgslOut->wgsl;
|
||||
return true;
|
||||
#else
|
||||
slog.i << "Trying to emit WGSL without including WebGPU dependencies, please set CMake arg FILAMENT_SUPPORTS_WEBGPU and FILAMENT_SUPPORTS_WEBGPU" << io::endl;
|
||||
slog.i << "Trying to emit WGSL without including WebGPU dependencies,"
|
||||
" please set CMake arg FILAMENT_SUPPORTS_WEBGPU and FILAMENT_SUPPORTS_WEBGPU"
|
||||
<< io::endl;
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@@ -971,7 +1008,8 @@ void GLSLPostProcessor::optimizeSpirv(OptimizerPtr optimizer, SpirvBlob& spirv)
|
||||
}
|
||||
|
||||
// Remove dead module-level objects: functions, types, vars
|
||||
SpirvRemapWrapperRemap(spirv);
|
||||
spv::spirvbin_t remapper(0);
|
||||
remapper.remap(spirv, spv::spirvbin_base_t::DCE_ALL);
|
||||
}
|
||||
|
||||
void GLSLPostProcessor::fixupClipDistance(
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <private/filament/SamplerInterfaceBlock.h>
|
||||
|
||||
#include "ShaderMinifier.h"
|
||||
#include "SpirvRemapWrapper.h"
|
||||
|
||||
#include <spirv-tools/optimizer.hpp>
|
||||
|
||||
|
||||
@@ -302,8 +302,7 @@ MaterialBuilder& MaterialBuilder::parameter(const char* name, UniformType const
|
||||
|
||||
|
||||
MaterialBuilder& MaterialBuilder::parameter(const char* name, SamplerType samplerType,
|
||||
SamplerFormat format, ParameterPrecision precision, bool multisample,
|
||||
const char* transformName, ShaderStageFlags stages) noexcept {
|
||||
SamplerFormat format, ParameterPrecision precision, bool multisample, const char* transformName) noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(!multisample ||
|
||||
(format != SamplerFormat::SHADOW &&
|
||||
(samplerType == SamplerType::SAMPLER_2D ||
|
||||
@@ -312,7 +311,7 @@ MaterialBuilder& MaterialBuilder::parameter(const char* name, SamplerType sample
|
||||
" as long as type is not SHADOW";
|
||||
|
||||
FILAMENT_CHECK_POSTCONDITION(mParameterCount < MAX_PARAMETERS_COUNT) << "Too many parameters";
|
||||
mParameters[mParameterCount++] = { name, samplerType, format, precision, multisample, transformName, stages };
|
||||
mParameters[mParameterCount++] = { name, samplerType, format, precision, multisample, transformName };
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -638,8 +637,8 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept {
|
||||
auto const& param = mParameters[i];
|
||||
assert_invariant(!param.isSubpass());
|
||||
if (param.isSampler()) {
|
||||
sbb.add({ param.name.data(), param.name.size() }, binding, param.samplerType,
|
||||
param.format, param.precision, param.multisample, param.stages);
|
||||
sbb.add({ param.name.data(), param.name.size() },
|
||||
binding, param.samplerType, param.format, param.precision, param.multisample);
|
||||
if (!param.transformName.empty()) {
|
||||
ibb.add({{{ param.transformName.data(), param.transformName.size() }, uint8_t(binding),
|
||||
0, UniformType::MAT3, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 }});
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#include "SpirvRemapWrapper.h"
|
||||
|
||||
#include <SPVRemapper.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace filamat {
|
||||
|
||||
void SpirvRemapWrapperSetUp() {
|
||||
// SPIRV error handler registration should occur only once.
|
||||
// Construct this SpirvRemapWrapper object only once.
|
||||
spv::spirvbin_t::registerErrorHandler([](const std::string& str) {
|
||||
utils::slog.e << str << utils::io::endl;
|
||||
});
|
||||
|
||||
// Similar to above, we need to do a no-op remap to init a static
|
||||
// table in the remapper before the jobs start using remap().
|
||||
spv::spirvbin_t remapper(0);
|
||||
// We need to provide at least a valid header to not crash.
|
||||
std::vector<uint32_t> spirv {
|
||||
0x07230203,// MAGIC
|
||||
0, // VERSION
|
||||
0, // GENERATOR
|
||||
0, // BOUND
|
||||
0 // SCHEMA, must be 0
|
||||
};
|
||||
remapper.remap(spirv, 0);
|
||||
}
|
||||
|
||||
void SpirvRemapWrapperRemap(std::vector<uint32_t>& spirv) {
|
||||
// Remove dead module-level objects: functions, types, vars
|
||||
spv::spirvbin_t remapper(0);
|
||||
remapper.remap(spirv, spv::spirvbin_base_t::DCE_ALL);
|
||||
}
|
||||
|
||||
} // namespace filamat
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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_SPIRVREMAPWRAPPER_H
|
||||
#define TNT_SPIRVREMAPWRAPPER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace filamat {
|
||||
|
||||
void SpirvRemapWrapperSetUp();
|
||||
void SpirvRemapWrapperRemap(std::vector<uint32_t>& spirv);
|
||||
|
||||
} // namespace filamat
|
||||
|
||||
#endif //TNT_SPIRVREMAPWRAPPER_H
|
||||
@@ -27,7 +27,10 @@
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
@@ -194,11 +197,7 @@ void MaterialDescriptorBindingsChuck::flatten(Flattener& f) {
|
||||
// all the material's sampler descriptors
|
||||
for (auto const& entry: mSamplerInterfaceBlock.getSamplerInfoList()) {
|
||||
f.writeString({ entry.uniformName.data(), entry.uniformName.size() });
|
||||
if (entry.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
|
||||
f.writeUint8(uint8_t(DescriptorType::SAMPLER_EXTERNAL));
|
||||
} else {
|
||||
f.writeUint8(uint8_t(DescriptorType::SAMPLER));
|
||||
}
|
||||
f.writeUint8(uint8_t(descriptor_sets::getDescriptorType(entry.type, entry.format)));
|
||||
f.writeUint8(entry.binding);
|
||||
}
|
||||
}
|
||||
@@ -228,12 +227,8 @@ void MaterialDescriptorSetLayoutChunk::flatten(Flattener& f) {
|
||||
|
||||
// all the material's sampler descriptors
|
||||
for (auto const& entry: mSamplerInterfaceBlock.getSamplerInfoList()) {
|
||||
if (entry.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
|
||||
f.writeUint8(uint8_t(DescriptorType::SAMPLER_EXTERNAL));
|
||||
} else {
|
||||
f.writeUint8(uint8_t(DescriptorType::SAMPLER));
|
||||
}
|
||||
f.writeUint8(uint8_t(entry.stages));
|
||||
f.writeUint8(uint8_t(descriptor_sets::getDescriptorType(entry.type, entry.format)));
|
||||
f.writeUint8(uint8_t(ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT));
|
||||
f.writeUint8(entry.binding);
|
||||
f.writeUint8(uint8_t(DescriptorFlags::NONE));
|
||||
f.writeUint16(0);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@@ -46,9 +47,9 @@ using namespace filament;
|
||||
using namespace filament::backend;
|
||||
using namespace utils;
|
||||
|
||||
void ShaderGenerator::generateSurfaceMaterialVariantDefines(utils::io::sstream& out,
|
||||
ShaderStage stage, MaterialBuilder::FeatureLevel featureLevel,
|
||||
MaterialInfo const& material, filament::Variant variant) noexcept {
|
||||
void ShaderGenerator::generateSurfaceMaterialVariantDefines(io::sstream& out,
|
||||
ShaderStage const stage, MaterialBuilder::FeatureLevel featureLevel,
|
||||
MaterialInfo const& material, filament::Variant const variant) noexcept {
|
||||
|
||||
bool const litVariants = material.isLit || material.hasShadowMultiplier;
|
||||
|
||||
@@ -228,25 +229,25 @@ void ShaderGenerator::generateSurfaceMaterialVariantProperties(io::sstream& out,
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGenerator::generateVertexDomainDefines(io::sstream& vs, VertexDomain domain) noexcept {
|
||||
void ShaderGenerator::generateVertexDomainDefines(io::sstream& out, VertexDomain const domain) noexcept {
|
||||
switch (domain) {
|
||||
case VertexDomain::OBJECT:
|
||||
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_OBJECT", true);
|
||||
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_OBJECT", true);
|
||||
break;
|
||||
case VertexDomain::WORLD:
|
||||
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_WORLD", true);
|
||||
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_WORLD", true);
|
||||
break;
|
||||
case VertexDomain::VIEW:
|
||||
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_VIEW", true);
|
||||
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_VIEW", true);
|
||||
break;
|
||||
case VertexDomain::DEVICE:
|
||||
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_DEVICE", true);
|
||||
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_DEVICE", true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGenerator::generatePostProcessMaterialVariantDefines(io::sstream& out,
|
||||
PostProcessVariant variant) noexcept {
|
||||
PostProcessVariant const variant) noexcept {
|
||||
switch (variant) {
|
||||
case PostProcessVariant::OPAQUE:
|
||||
CodeGenerator::generateDefine(out, "POST_PROCESS_OPAQUE", 1u);
|
||||
@@ -258,7 +259,7 @@ void ShaderGenerator::generatePostProcessMaterialVariantDefines(io::sstream& out
|
||||
}
|
||||
|
||||
void ShaderGenerator::appendShader(io::sstream& ss,
|
||||
const CString& shader, size_t lineOffset) noexcept {
|
||||
const CString& shader, size_t const lineOffset) noexcept {
|
||||
|
||||
auto countLines = [](const char* s) -> size_t {
|
||||
size_t lines = 0;
|
||||
@@ -314,9 +315,9 @@ ShaderGenerator::ShaderGenerator(
|
||||
MaterialBuilder::PreprocessorDefineList const& defines,
|
||||
MaterialBuilder::ConstantList const& constants,
|
||||
MaterialBuilder::PushConstantList const& pushConstants,
|
||||
CString const& materialCode, size_t lineOffset,
|
||||
CString const& materialVertexCode, size_t vertexLineOffset,
|
||||
MaterialBuilder::MaterialDomain materialDomain) noexcept {
|
||||
CString const& materialCode, size_t const lineOffset,
|
||||
CString const& materialVertexCode, size_t const vertexLineOffset,
|
||||
MaterialBuilder::MaterialDomain const materialDomain) noexcept {
|
||||
|
||||
if (materialDomain == MaterialBuilder::MaterialDomain::COMPUTE) {
|
||||
// we shouldn't have a vertex shader in a compute material
|
||||
@@ -360,8 +361,8 @@ ShaderGenerator::ShaderGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGenerator::fixupExternalSamplers(ShaderModel sm, std::string& shader,
|
||||
MaterialBuilder::FeatureLevel featureLevel,
|
||||
void ShaderGenerator::fixupExternalSamplers(ShaderModel const sm, std::string& shader,
|
||||
MaterialBuilder::FeatureLevel const featureLevel,
|
||||
MaterialInfo const& material) noexcept {
|
||||
// External samplers are only supported on GL ES at the moment, we must
|
||||
// skip the fixup on desktop targets
|
||||
@@ -370,11 +371,11 @@ void ShaderGenerator::fixupExternalSamplers(ShaderModel sm, std::string& shader,
|
||||
}
|
||||
}
|
||||
|
||||
std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel,
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
MaterialBuilder::FeatureLevel featureLevel,
|
||||
MaterialInfo const& material, const filament::Variant variant, Interpolation interpolation,
|
||||
VertexDomain vertexDomain) const noexcept {
|
||||
std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel const shaderModel,
|
||||
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
|
||||
MaterialBuilder::FeatureLevel const featureLevel,
|
||||
MaterialInfo const& material, const filament::Variant variant, Interpolation const interpolation,
|
||||
VertexDomain const vertexDomain) const noexcept {
|
||||
|
||||
assert_invariant(filament::Variant::isValid(variant));
|
||||
assert_invariant(mMaterialDomain != MaterialBuilder::MaterialDomain::COMPUTE);
|
||||
@@ -416,23 +417,23 @@ std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel,
|
||||
|
||||
AttributeBitset attributes = material.requiredAttributes;
|
||||
if (hasSkinningOrMorphing(variant, featureLevel)) {
|
||||
attributes.set(VertexAttribute::BONE_INDICES);
|
||||
attributes.set(VertexAttribute::BONE_WEIGHTS);
|
||||
attributes.set(BONE_INDICES);
|
||||
attributes.set(BONE_WEIGHTS);
|
||||
if (material.useLegacyMorphing) {
|
||||
attributes.set(VertexAttribute::MORPH_POSITION_0);
|
||||
attributes.set(VertexAttribute::MORPH_POSITION_1);
|
||||
attributes.set(VertexAttribute::MORPH_POSITION_2);
|
||||
attributes.set(VertexAttribute::MORPH_POSITION_3);
|
||||
attributes.set(VertexAttribute::MORPH_TANGENTS_0);
|
||||
attributes.set(VertexAttribute::MORPH_TANGENTS_1);
|
||||
attributes.set(VertexAttribute::MORPH_TANGENTS_2);
|
||||
attributes.set(VertexAttribute::MORPH_TANGENTS_3);
|
||||
attributes.set(MORPH_POSITION_0);
|
||||
attributes.set(MORPH_POSITION_1);
|
||||
attributes.set(MORPH_POSITION_2);
|
||||
attributes.set(MORPH_POSITION_3);
|
||||
attributes.set(MORPH_TANGENTS_0);
|
||||
attributes.set(MORPH_TANGENTS_1);
|
||||
attributes.set(MORPH_TANGENTS_2);
|
||||
attributes.set(MORPH_TANGENTS_3);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialBuilder::PushConstantList vertexPushConstants;
|
||||
std::copy_if(mPushConstants.begin(), mPushConstants.end(),
|
||||
std::back_insert_iterator<MaterialBuilder::PushConstantList>(vertexPushConstants),
|
||||
std::back_insert_iterator(vertexPushConstants),
|
||||
[](MaterialBuilder::PushConstant const& constant) {
|
||||
return constant.stage == ShaderStage::VERTEX;
|
||||
});
|
||||
@@ -505,11 +506,11 @@ std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel,
|
||||
return vs.c_str();
|
||||
}
|
||||
|
||||
std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderModel,
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
MaterialBuilder::FeatureLevel featureLevel,
|
||||
std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel const shaderModel,
|
||||
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
|
||||
MaterialBuilder::FeatureLevel const featureLevel,
|
||||
MaterialInfo const& material, const filament::Variant variant,
|
||||
Interpolation interpolation, UserVariantFilterMask variantFilter) const noexcept {
|
||||
Interpolation const interpolation, UserVariantFilterMask const variantFilter) const noexcept {
|
||||
|
||||
assert_invariant(filament::Variant::isValid(variant));
|
||||
assert_invariant(mMaterialDomain != MaterialBuilder::MaterialDomain::COMPUTE);
|
||||
@@ -529,8 +530,8 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
|
||||
generateSurfaceMaterialVariantDefines(
|
||||
fs, ShaderStage::FRAGMENT, featureLevel, material, variant);
|
||||
|
||||
auto defaultSpecularAO = shaderModel == ShaderModel::MOBILE ?
|
||||
SpecularAmbientOcclusion::NONE : SpecularAmbientOcclusion::SIMPLE;
|
||||
auto const defaultSpecularAO = shaderModel == ShaderModel::MOBILE ?
|
||||
SpecularAmbientOcclusion::NONE : SpecularAmbientOcclusion::SIMPLE;
|
||||
auto specularAO = material.specularAOSet ? material.specularAO : defaultSpecularAO;
|
||||
CodeGenerator::generateDefine(fs, "SPECULAR_AMBIENT_OCCLUSION", uint32_t(specularAO));
|
||||
|
||||
@@ -542,12 +543,12 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
|
||||
|
||||
MaterialBuilder::PushConstantList fragmentPushConstants;
|
||||
std::copy_if(mPushConstants.begin(), mPushConstants.end(),
|
||||
std::back_insert_iterator<MaterialBuilder::PushConstantList>(fragmentPushConstants),
|
||||
std::back_insert_iterator(fragmentPushConstants),
|
||||
[](MaterialBuilder::PushConstant const& constant) {
|
||||
return constant.stage == ShaderStage::FRAGMENT;
|
||||
});
|
||||
cg.generateSurfaceShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes, interpolation,
|
||||
fragmentPushConstants);
|
||||
cg.generateSurfaceShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes,
|
||||
interpolation, fragmentPushConstants);
|
||||
|
||||
CodeGenerator::generateSurfaceTypes(fs, ShaderStage::FRAGMENT);
|
||||
|
||||
@@ -605,12 +606,16 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
|
||||
if (featureLevel >= FeatureLevel::FEATURE_LEVEL_1) {
|
||||
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
|
||||
// this is the list of samplers we need to filter
|
||||
|
||||
bool const isLit = material.isLit || material.hasShadowMultiplier;
|
||||
bool const isSSR = material.reflectionMode == ReflectionMode::SCREEN_SPACE ||
|
||||
material.refractionMode == RefractionMode::SCREEN_SPACE;
|
||||
bool const hasFog = !(variantFilter & UserVariantFilterMask(UserVariantFilterBit::FOG));
|
||||
|
||||
auto const list = SamplerInterfaceBlock::filterSamplerList(
|
||||
SibGenerator::getPerViewSib(variant).getSamplerInfoList(),
|
||||
descriptor_sets::getPerViewDescriptorSetLayoutWithVariant(
|
||||
variant, mMaterialDomain, variantFilter,
|
||||
material.isLit || material.hasShadowMultiplier,
|
||||
material.reflectionMode, material.refractionMode));
|
||||
variant, mMaterialDomain, isLit, isSSR, hasFog));
|
||||
|
||||
cg.generateCommonSamplers(fs, DescriptorSetBindingPoints::PER_VIEW, list);
|
||||
}
|
||||
@@ -665,9 +670,9 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
|
||||
return fs.c_str();
|
||||
}
|
||||
|
||||
std::string ShaderGenerator::createSurfaceComputeProgram(filament::backend::ShaderModel shaderModel,
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
MaterialBuilder::FeatureLevel featureLevel,
|
||||
std::string ShaderGenerator::createSurfaceComputeProgram(ShaderModel const shaderModel,
|
||||
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
|
||||
MaterialBuilder::FeatureLevel const featureLevel,
|
||||
MaterialInfo const& material) const noexcept {
|
||||
assert_invariant(mMaterialDomain == MaterialBuilder::MaterialDomain::COMPUTE);
|
||||
assert_invariant(featureLevel >= FeatureLevel::FEATURE_LEVEL_2);
|
||||
@@ -708,9 +713,9 @@ std::string ShaderGenerator::createSurfaceComputeProgram(filament::backend::Shad
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
MaterialBuilder::FeatureLevel featureLevel,
|
||||
std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel const sm,
|
||||
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
|
||||
MaterialBuilder::FeatureLevel const featureLevel,
|
||||
MaterialInfo const& material, const filament::Variant::type_t variantKey) const noexcept {
|
||||
const CodeGenerator cg(sm, targetApi, targetLanguage, featureLevel);
|
||||
io::sstream vs;
|
||||
@@ -718,7 +723,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
|
||||
|
||||
generateUserSpecConstants(cg, vs, mConstants);
|
||||
|
||||
CodeGenerator::generateDefine(vs, "LOCATION_POSITION", uint32_t(VertexAttribute::POSITION));
|
||||
CodeGenerator::generateDefine(vs, "LOCATION_POSITION", uint32_t(POSITION));
|
||||
|
||||
// custom material variables
|
||||
size_t variableIndex = 0;
|
||||
@@ -752,9 +757,9 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
|
||||
return vs.c_str();
|
||||
}
|
||||
|
||||
std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
MaterialBuilder::FeatureLevel featureLevel,
|
||||
std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel const sm,
|
||||
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
|
||||
MaterialBuilder::FeatureLevel const featureLevel,
|
||||
MaterialInfo const& material, uint8_t variant) const noexcept {
|
||||
const CodeGenerator cg(sm, targetApi, targetLanguage, featureLevel);
|
||||
io::sstream fs;
|
||||
@@ -811,7 +816,7 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
|
||||
}
|
||||
|
||||
bool ShaderGenerator::hasSkinningOrMorphing(
|
||||
filament::Variant variant, MaterialBuilder::FeatureLevel featureLevel) noexcept {
|
||||
filament::Variant const variant, MaterialBuilder::FeatureLevel const featureLevel) noexcept {
|
||||
return variant.hasSkinningOrMorphing()
|
||||
// HACK(exv): Ignore skinning/morphing variant when targeting ESSL 1.0. We should
|
||||
// either properly support skinning on FL0 or build a system in matc which allows
|
||||
@@ -820,7 +825,7 @@ bool ShaderGenerator::hasSkinningOrMorphing(
|
||||
}
|
||||
|
||||
bool ShaderGenerator::hasStereo(
|
||||
filament::Variant variant, MaterialBuilder::FeatureLevel featureLevel) noexcept {
|
||||
filament::Variant const variant, MaterialBuilder::FeatureLevel const featureLevel) noexcept {
|
||||
return variant.hasStereo()
|
||||
// HACK(exv): Ignore stereo variant when targeting ESSL 1.0. We should properly build a
|
||||
// system in matc which allows the set of included variants to differ per-feature level.
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <filamat/MaterialBuilder.h>
|
||||
|
||||
#include <utils/JobSystem.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <utils/JobSystem.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::math;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <geometry/TangentSpaceMesh.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/StructureOfArrays.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <string_view>
|
||||
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
using namespace utils;
|
||||
using namespace std::literals;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user