Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee4d59a743 | ||
|
|
8812a35cbd | ||
|
|
35d7b819e1 | ||
|
|
9b2959d3a4 |
@@ -691,11 +691,6 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=stereo)
|
||||
endif()
|
||||
|
||||
# Disable ESSL 1.0 code generation.
|
||||
if (NOT FILAMENT_ENABLE_FEATURE_LEVEL_0)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -1)
|
||||
endif()
|
||||
|
||||
# Enable debug info (preserves names in SPIR-V)
|
||||
if (FILAMENT_ENABLE_MATDBG)
|
||||
set(MATC_OPT_FLAGS ${MATC_OPT_FLAGS} -d)
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#include <filament/Texture.h>
|
||||
#include <filament/TextureSampler.h>
|
||||
|
||||
#include "common/CallbackUtils.h"
|
||||
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec2.h>
|
||||
@@ -258,69 +256,6 @@ Java_com_google_android_filament_MaterialInstance_nSetFloatParameterArray(JNIEnv
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetConstantBool(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
const char *name = env->GetStringUTFChars(name_, 0);
|
||||
jboolean result = instance->getConstant<bool>(name);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jfloat JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetConstantFloat(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
const char *name = env->GetStringUTFChars(name_, 0);
|
||||
jfloat result = instance->getConstant<float>(name);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetConstantInt(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
const char *name = env->GetStringUTFChars(name_, 0);
|
||||
jint result = instance->getConstant<int32_t>(name);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetConstantBool(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jboolean x) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
const char *name = env->GetStringUTFChars(name_, 0);
|
||||
instance->setConstant<bool>(name, x);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetConstantFloat(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jfloat x) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
const char *name = env->GetStringUTFChars(name_, 0);
|
||||
instance->setConstant<float>(name, x);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetConstantInt(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jint x) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
const char *name = env->GetStringUTFChars(name_, 0);
|
||||
instance->setConstant<int32_t>(name, x);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
// defined in TextureSampler.cpp
|
||||
namespace filament::JniUtils {
|
||||
TextureSampler from_long(jlong params) noexcept;
|
||||
@@ -657,17 +592,3 @@ Java_com_google_android_filament_MaterialInstance_nGetTransparencyMode(JNIEnv*,
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
return (jint) instance->getTransparencyMode();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nCompile(JNIEnv *env, jclass clazz,
|
||||
jlong nativeMaterialInstance, jint priority, jint variants, jobject handler, jobject runnable) {
|
||||
MaterialInstance* materialInstance = (MaterialInstance*) nativeMaterialInstance;
|
||||
JniCallback* jniCallback = JniCallback::make(env, handler, runnable);
|
||||
materialInstance->compile(
|
||||
(MaterialInstance::CompilerPriorityQueue) priority,
|
||||
(UserVariantFilterBit) variants,
|
||||
jniCallback->getHandler(), [jniCallback](MaterialInstance*){
|
||||
JniCallback::postToJavaAndDestroy(jniCallback);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -523,19 +523,11 @@ public class Material {
|
||||
* for stereoscopic rendering. If an application is not planning to render in stereo, this bit
|
||||
* should be turned off to avoid unnecessary material compilations.
|
||||
*</p>
|
||||
*<p>
|
||||
* Note that it is possible to override specialization constants on a per-MaterialInstance basis
|
||||
* (see {@link MaterialInstance#setConstant}). In that case, the programs compiled by a call to
|
||||
* Material::compile() may not be reusable by that MaterialInstance. It's better to call
|
||||
* MaterialInstance::compile() in cases where you intend to override specialization constants.
|
||||
*</p>
|
||||
* @param priority Which priority queue to use, LOW or HIGH.
|
||||
* @param variants Variants to include to the compile command.
|
||||
* @param handler An {@link java.util.concurrent.Executor Executor}. On Android this can also be a {@link android.os.Handler Handler}.
|
||||
* @param callback callback called on the main thread when the compilation is done on
|
||||
* by backend.
|
||||
*
|
||||
* @see MaterialInstance#compile
|
||||
*/
|
||||
public void compile(@NonNull CompilerPriorityQueue priority,
|
||||
int variants,
|
||||
|
||||
-98
@@ -18,7 +18,6 @@ package com.google.android.filament;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Size;
|
||||
|
||||
import com.google.android.filament.proguard.UsedByNative;
|
||||
@@ -143,28 +142,6 @@ public class MaterialInstance {
|
||||
return mMaterial;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously ensures that a subset of this MaterialInstance's variants are compiled.
|
||||
*
|
||||
* <p>This function behaves identically to {@link Material#compile}, but takes into account
|
||||
* the specific constants overridden by {@link #setConstant}.</p>
|
||||
*
|
||||
* @param priority Priority of the compile command.
|
||||
* @param variants Variants to include to the compile command.
|
||||
* @param handler An {@link java.util.concurrent.Executor Executor}. On Android this can also be a {@link android.os.Handler Handler}.
|
||||
* @param callback callback called on the main thread when the compilation is done on
|
||||
* by backend.
|
||||
*
|
||||
* @see Material#compile
|
||||
* @see #setConstant
|
||||
*/
|
||||
public void compile(@NonNull Material.CompilerPriorityQueue priority,
|
||||
int variants,
|
||||
@Nullable Object handler,
|
||||
@Nullable Runnable callback) {
|
||||
nCompile(getNativeObject(), priority.ordinal(), variants, handler, callback);
|
||||
}
|
||||
|
||||
/** @return the name associated with this instance */
|
||||
@NonNull
|
||||
public String getName() {
|
||||
@@ -443,69 +420,6 @@ public class MaterialInstance {
|
||||
nSetParameterFloat4(getNativeObject(), name, color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides a specialization constant of this material instance.
|
||||
*
|
||||
* @param name The name of the constant as defined in the material.
|
||||
* @param value The value of the constant.
|
||||
* @see Material.Builder#constant
|
||||
*/
|
||||
public void setConstant(@NonNull String name, boolean value) {
|
||||
nSetConstantBool(getNativeObject(), name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides a specialization constant of this material instance.
|
||||
*
|
||||
* @param name The name of the constant as defined in the material.
|
||||
* @param value The value of the constant.
|
||||
* @see Material.Builder#constant
|
||||
*/
|
||||
public void setConstant(@NonNull String name, float value) {
|
||||
nSetConstantFloat(getNativeObject(), name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides a specialization constant of this material instance.
|
||||
*
|
||||
* @param name The name of the constant as defined in the material.
|
||||
* @param value The value of the constant.
|
||||
* @see Material.Builder#constant
|
||||
*/
|
||||
public void setConstant(@NonNull String name, int value) {
|
||||
nSetConstantInt(getNativeObject(), name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a specialization constant by name.
|
||||
*
|
||||
* @param name The name of the constant as defined in the material.
|
||||
* @return The value of the constant.
|
||||
*/
|
||||
public boolean getConstantBoolean(@NonNull String name) {
|
||||
return nGetConstantBool(getNativeObject(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a specialization constant by name.
|
||||
*
|
||||
* @param name The name of the constant as defined in the material.
|
||||
* @return The value of the constant.
|
||||
*/
|
||||
public float getConstantFloat(@NonNull String name) {
|
||||
return nGetConstantFloat(getNativeObject(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a specialization constant by name.
|
||||
*
|
||||
* @param name The name of the constant as defined in the material.
|
||||
* @return The value of the constant.
|
||||
*/
|
||||
public int getConstantInt(@NonNull String name) {
|
||||
return nGetConstantInt(getNativeObject(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set-up a custom scissor rectangle; by default it is disabled.
|
||||
*
|
||||
@@ -1041,17 +955,6 @@ public class MaterialInstance {
|
||||
@NonNull String name, int element, @NonNull @Size(min = 1) float[] v,
|
||||
@IntRange(from = 0) int offset, @IntRange(from = 1) int count);
|
||||
|
||||
private static native boolean nGetConstantBool(long nativeMaterialInstance, @NonNull String name);
|
||||
private static native float nGetConstantFloat(long nativeMaterialInstance, @NonNull String name);
|
||||
private static native int nGetConstantInt(long nativeMaterialInstance, @NonNull String name);
|
||||
|
||||
private static native void nSetConstantBool(long nativeMaterialInstance,
|
||||
@NonNull String name, boolean x);
|
||||
private static native void nSetConstantFloat(long nativeMaterialInstance,
|
||||
@NonNull String name, float x);
|
||||
private static native void nSetConstantInt(long nativeMaterialInstance,
|
||||
@NonNull String name, int x);
|
||||
|
||||
private static native void nSetParameterTexture(long nativeMaterialInstance,
|
||||
@NonNull String name, long nativeTexture, long sampler);
|
||||
|
||||
@@ -1115,5 +1018,4 @@ public class MaterialInstance {
|
||||
private static native int nGetDepthFunc(long nativeMaterialInstance);
|
||||
private static native void nSetTransparencyMode(long nativeMaterialInstance, int mode);
|
||||
private static native int nGetTransparencyMode(long nativeMaterialInstance);
|
||||
private static native void nCompile(long nativeMaterialInstance, int priority, int variants, Object handler, Runnable callback);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ set -e
|
||||
|
||||
# Host tools required by Android, WASM, and iOS builds
|
||||
MOBILE_HOST_TOOLS="matc resgen cmgen filamesh uberz"
|
||||
WEB_HOST_TOOLS="${MOBILE_HOST_TOOLS} mipgen filamesh"
|
||||
WEB_HOST_TOOLS="${MOBILE_HOST_TOOLS} mipgen filamesh glslminifier"
|
||||
|
||||
function print_help {
|
||||
local self_name=$(basename "$0")
|
||||
|
||||
@@ -134,7 +134,23 @@ pushd .
|
||||
cd ${MESA_DIR}
|
||||
|
||||
# Need >= 24 to have llvmpipe for swrast. llvmpipe is needed for GL >= 4.1.
|
||||
git checkout mesa-${MESA_VERSION}
|
||||
git checkout -f mesa-${MESA_VERSION}
|
||||
|
||||
# Apply custom patch to fix a double-free in OSMesa
|
||||
git apply << 'EOF'
|
||||
diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
|
||||
index 74bd6a6c33b..a70814e53a1 100644
|
||||
--- a/src/mesa/program/program.c
|
||||
+++ b/src/mesa/program/program.c
|
||||
@@ -130,6 +130,7 @@ _mesa_free_program_data(struct gl_context *ctx)
|
||||
ctx->ATIFragmentShader.Current->RefCount--;
|
||||
if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
|
||||
free(ctx->ATIFragmentShader.Current);
|
||||
+ ctx->ATIFragmentShader.Current = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
mkdir -p out
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -75,7 +75,8 @@ private:
|
||||
OSMesaContext context;
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
};
|
||||
std::unordered_map<std::thread::id, ContextInfo> mAdditionalContexts;
|
||||
using ContextMap = std::unordered_map<std::thread::id, ContextInfo>;
|
||||
ContextMap mAdditionalContexts;
|
||||
mutable std::shared_mutex mAdditionalContextsLock;
|
||||
};
|
||||
|
||||
|
||||
@@ -403,6 +403,9 @@ void OpenGLDriver::terminate() {
|
||||
if (getJobWorker()) {
|
||||
getJobWorker()->terminate();
|
||||
}
|
||||
// wait for the GPU again because JobWorker might have queued more work.
|
||||
glFinish();
|
||||
|
||||
if constexpr (UTILS_HAS_THREADING) {
|
||||
stopServiceThread();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/ThreadUtils.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <dlfcn.h>
|
||||
#include <memory>
|
||||
|
||||
@@ -203,6 +204,7 @@ void PlatformOSMesa::createContext(bool shared) {
|
||||
void PlatformOSMesa::releaseContext() noexcept {
|
||||
std::thread::id currentThreadId = utils::ThreadUtils::getThreadId();
|
||||
OSMesaContext context = nullptr;
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock(mAdditionalContextsLock);
|
||||
@@ -212,16 +214,15 @@ void PlatformOSMesa::releaseContext() noexcept {
|
||||
return;
|
||||
}
|
||||
context = it->second.context;
|
||||
buffer = std::move(it->second.buffer);
|
||||
mAdditionalContexts.erase(it);
|
||||
}
|
||||
|
||||
OSMesaAPI* api = (OSMesaAPI*) mOsMesaApi;
|
||||
// Passing NULL as the context is the standard way to unbind in OSMesa.
|
||||
api->fOSMesaMakeCurrent(NULL, NULL, 0, 0, 0);
|
||||
api->fOSMesaDestroyContext(context);
|
||||
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock(mAdditionalContextsLock);
|
||||
mAdditionalContexts.erase(currentThreadId);
|
||||
if (api) {
|
||||
// Passing NULL as the context is the standard way to unbind in OSMesa.
|
||||
api->fOSMesaMakeCurrent(NULL, NULL, 0, 0, 0);
|
||||
api->fOSMesaDestroyContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,101 +43,6 @@ namespace filament::backend {
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Given the source code of a [WGSL] WebGPU shader in text (string view to it) and the constants
|
||||
* to be overwritten now (at runtime), returns updated [WGSL] shader code text, where the constants
|
||||
* have been replaced.
|
||||
* @param shaderLabel Something to call this shader for troubleshooting, error messaging, etc.
|
||||
* @param shaderSource The original WGSL WebGPU shader code as text to be processed. This is a
|
||||
* view to that text and this function does not change it; it is immutable.
|
||||
* Instead, the processed version of this source is returned by the function.
|
||||
* @param specConstants The constants to replace in the shader code, indexed by constant id.
|
||||
* @return Processed version of the WGSL WebGPU shader code provided, where the constants have
|
||||
* been replaced with the values provided by the specConstants parameter.
|
||||
*/
|
||||
[[nodiscard]] std::string replaceSpecConstants(std::string_view shaderLabel,
|
||||
std::string_view shaderSource,
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specConstants) {
|
||||
// this function is not expected to be called at all if no spec constants are to be replaced
|
||||
assert_invariant(!specConstants.empty());
|
||||
static constexpr std::string_view specConstantPrefix = "FILAMENT_SPEC_CONST_";
|
||||
static constexpr size_t specConstantPrefixSize = specConstantPrefix.size();
|
||||
const char* const sourceData = shaderSource.data();
|
||||
std::stringstream processedShaderSource{};
|
||||
size_t pos = 0;
|
||||
while (pos < shaderSource.size()) {
|
||||
const size_t posOfNextSpecConstant = shaderSource.find(specConstantPrefix, pos);
|
||||
if (posOfNextSpecConstant == std::string::npos) {
|
||||
// no more spec constants, so just stream the rest of the source code string
|
||||
processedShaderSource << std::string_view(sourceData + pos, shaderSource.size() - pos);
|
||||
break;
|
||||
}
|
||||
const size_t posOfId = posOfNextSpecConstant + specConstantPrefixSize;
|
||||
const size_t posAfterId = shaderSource.find('_', posOfId);
|
||||
FILAMENT_CHECK_POSTCONDITION(posAfterId != std::string::npos)
|
||||
<< "malformed " << shaderLabel << ". Found spec constant prefix '"
|
||||
<< specConstantPrefix << "' without an id or '_' after it.";
|
||||
const std::string_view idStr =
|
||||
std::string_view(sourceData + posOfId, posAfterId - posOfId);
|
||||
const size_t posEndOfStatement = shaderSource.find(';', posAfterId);
|
||||
FILAMENT_CHECK_POSTCONDITION(posEndOfStatement != std::string::npos)
|
||||
<< "malformed " << shaderLabel << ". Found spec constant assignment with id "
|
||||
<< idStr << " without a terminating ';' character?";
|
||||
// this is a view into part of the statement, from after the id to the ';'
|
||||
const std::string_view statementSegment =
|
||||
std::string_view(sourceData + posAfterId, posEndOfStatement - posAfterId);
|
||||
size_t posOfEqual = statementSegment.find('=');
|
||||
if (posOfEqual == std::string::npos) {
|
||||
// Not an assignment, so we don't need to replace it.
|
||||
processedShaderSource << std::string_view(sourceData + pos,
|
||||
posEndOfStatement + 1 - pos);
|
||||
pos = posEndOfStatement + 1;
|
||||
continue;
|
||||
}
|
||||
posOfEqual += posAfterId; // position in original source overall, not just the segment
|
||||
int constantId = 0;
|
||||
char* endPtr;
|
||||
errno = 0; // Clear errno before the call
|
||||
|
||||
long tempConstantId = std::strtol(idStr.data(), &endPtr, 10);
|
||||
|
||||
// Check for conversion errors
|
||||
if (endPtr == idStr.data() || *endPtr != '\0' || errno == ERANGE) {
|
||||
// Parsing failed, or conversion was out of range for 'long'
|
||||
// or the string contained non-numeric characters after the number.
|
||||
PANIC_POSTCONDITION("Invalid spec constant id '%s' in %s (not a valid integer or out "
|
||||
"of range for 'long'?)",
|
||||
idStr.data(), shaderLabel.data());
|
||||
} else {
|
||||
// Check if the parsed long value fits into an int
|
||||
if (tempConstantId > std::numeric_limits<int>::max() ||
|
||||
tempConstantId < std::numeric_limits<int>::min()) {
|
||||
PANIC_POSTCONDITION(
|
||||
"Invalid spec constant id '%s' in %s (value out of range for 'int')",
|
||||
idStr.data(), shaderLabel.data());
|
||||
} else {
|
||||
constantId = static_cast<int>(tempConstantId);
|
||||
}
|
||||
}
|
||||
const std::variant<int32_t, float, bool> newValue = specConstants[constantId];
|
||||
// stream up to the equal sign...
|
||||
processedShaderSource << std::string_view(sourceData + pos, posOfEqual + 1 - pos);
|
||||
// stream the new value...
|
||||
if (auto* v = std::get_if<int32_t>(&newValue)) {
|
||||
processedShaderSource << " " << *v << "i";
|
||||
} else if (auto* f = std::get_if<float>(&newValue)) {
|
||||
processedShaderSource << " " << *f << "f";
|
||||
} else if (auto* b = std::get_if<bool>(&newValue)) {
|
||||
processedShaderSource << " " << ((*b) ? "true" : "false");
|
||||
}
|
||||
// end the statement...
|
||||
processedShaderSource << ";";
|
||||
// and skip to after the end of the statement in the original source and continue...
|
||||
pos = posEndOfStatement + 1;
|
||||
}
|
||||
return processedShaderSource.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a WebGPU shader module for a given "program" "stage", accounting for override constants.
|
||||
* Effectively, this function is responsible for preprocessing the shader source and compiling it.
|
||||
@@ -145,14 +50,12 @@ namespace {
|
||||
* a shader module
|
||||
* @param program The "program" to compile/create the shader, which includes the shader source
|
||||
* @param stage The stage (e.g. vertex, fragment, etc.) to create the shader module
|
||||
* @param specConstants Override constants to apply when creating/compiling the shader module.
|
||||
* @return the proper WebGPU shader module compiled/created from the input parameters. This might
|
||||
* wrap a null handle if the shader is not present (if the shader source is empty), such as
|
||||
* a missing fragment or compute shader.
|
||||
*/
|
||||
[[nodiscard]] wgpu::ShaderModule createShaderModule(wgpu::Device const& device,
|
||||
Program const& program, const ShaderStage stage,
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specConstants) {
|
||||
Program const& program, const ShaderStage stage) {
|
||||
const char* const programName = program.getName().c_str_safe();
|
||||
std::array<utils::FixedCapacityVector<uint8_t>, Program::SHADER_TYPE_COUNT> const&
|
||||
shaderSource = program.getShadersSource();
|
||||
@@ -164,13 +67,9 @@ namespace {
|
||||
std::stringstream labelStream;
|
||||
labelStream << programName << " " << filamentShaderStageToString(stage) << " shader";
|
||||
const auto label = labelStream.str();
|
||||
const std::string processedShaderSource =
|
||||
specConstants.empty()
|
||||
? reinterpret_cast<const char*>(sourceBytes.data())
|
||||
: replaceSpecConstants(label, reinterpret_cast<const char*>(sourceBytes.data()),
|
||||
specConstants);
|
||||
|
||||
wgpu::ShaderSourceWGSL wgslDescriptor{};
|
||||
wgslDescriptor.code = wgpu::StringView(processedShaderSource);
|
||||
wgslDescriptor.code = wgpu::StringView(reinterpret_cast<const char*>(sourceBytes.data()));
|
||||
const wgpu::ShaderModuleDescriptor descriptor{
|
||||
.nextInChain = &wgslDescriptor,
|
||||
.label = label.data()
|
||||
@@ -251,14 +150,11 @@ namespace {
|
||||
}// namespace
|
||||
|
||||
WebGPUProgram::WebGPUProgram(wgpu::Device const& device, Program const& program)
|
||||
: HwProgram{ program.getName() } {
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specConstants =
|
||||
program.getSpecializationConstants();
|
||||
: HwProgram{ program.getName() } {
|
||||
// TODO: Consider creating/compiling these shaders in parallel.
|
||||
vertexShaderModule = createShaderModule(device, program, ShaderStage::VERTEX, specConstants);
|
||||
fragmentShaderModule =
|
||||
createShaderModule(device, program, ShaderStage::FRAGMENT, specConstants);
|
||||
computeShaderModule = createShaderModule(device, program, ShaderStage::COMPUTE, specConstants);
|
||||
vertexShaderModule = createShaderModule(device, program, ShaderStage::VERTEX);
|
||||
fragmentShaderModule = createShaderModule(device, program, ShaderStage::FRAGMENT);
|
||||
computeShaderModule = createShaderModule(device, program, ShaderStage::COMPUTE);
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -225,42 +225,73 @@ struct AttributeInfo final {
|
||||
* associated with a vertex buffer, and the slot each one belongs
|
||||
*/
|
||||
void createBufferLayoutsBindingSlotsAndAttributeInfos(AttributeArray const& attributes,
|
||||
const uint8_t attributeCount, const uint32_t deviceMaxVertexBuffers,
|
||||
const uint32_t deviceMaxVertexBuffers,
|
||||
std::vector<WebGPUVertexBufferInfo::WebGPUSlotBindingInfo>& outWebGPUSlotBindingInfos,
|
||||
std::vector<wgpu::VertexBufferLayout>& outVertexBufferLayouts,
|
||||
std::array<AttributeInfo, MAX_VERTEX_ATTRIBUTE_COUNT>& outAttributeInfos) {
|
||||
std::array<AttributeInfo, MAX_VERTEX_ATTRIBUTE_COUNT>& outAttributeInfos,
|
||||
uint8_t& outActualAttributeCount) {
|
||||
uint8_t currentWebGPUSlotIndex = 0;
|
||||
uint8_t currentAttributeIndex = 0;
|
||||
outVertexBufferLayouts.reserve(MAX_VERTEX_BUFFER_COUNT);
|
||||
outWebGPUSlotBindingInfos.reserve(outVertexBufferLayouts.capacity());
|
||||
for (uint32_t attributeIndex = 0; attributeIndex < attributes.size(); ++attributeIndex) {
|
||||
const auto& attribute = attributes[attributeIndex];
|
||||
if (attribute.buffer == Attribute::BUFFER_UNUSED) {
|
||||
// We ignore "unused" attributes, ones not associated with a buffer. If a shader
|
||||
// references such an attribute we have a bug one way or another. Either the API/CPU
|
||||
// will produce an error (best case scenario), where an attribute is referenced in the
|
||||
// shader but not provided by the backend API (CPU-side), or the shader would be getting
|
||||
// junk/undefined data from the GPU, since we do not have a valid buffer of data to
|
||||
// provide to the shader/GPU.
|
||||
continue;
|
||||
|
||||
// Find a valid attribute to use as a dummy for unused slots (typically POSITION at index 0)
|
||||
Attribute dummyAttribute{};
|
||||
bool hasDummy = false;
|
||||
for (uint32_t i = 0; i < attributes.size(); ++i) {
|
||||
if (attributes[i].buffer != Attribute::BUFFER_UNUSED) {
|
||||
dummyAttribute = attributes[i];
|
||||
hasDummy = true;
|
||||
break;
|
||||
}
|
||||
const bool isInteger = attribute.flags & Attribute::FLAG_INTEGER_TARGET;
|
||||
const bool isNormalized = attribute.flags & Attribute::FLAG_NORMALIZED;
|
||||
const wgpu::VertexFormat vertexFormat =
|
||||
getVertexFormat(attribute.type, isNormalized, isInteger);
|
||||
}
|
||||
|
||||
/*
|
||||
* WebGPU Strict Validation Workaround:
|
||||
*
|
||||
* 1. Completeness: WebGPU requires ALL shader-declared attributes to exist in the Pipeline's
|
||||
* VertexState, even if unused by a specific mesh variant (e.g., BONE_WEIGHTS).
|
||||
* 2. Stride Boundary: Offset + Format_Size <= arrayStride.
|
||||
*
|
||||
* If we omit an unused attribute, WebGPU crashes (violates 1).
|
||||
* If we pad it as Float32x4 (16 bytes) into Slot 0 (e.g., Position, stride 12), WebGPU crashes
|
||||
* (violates 2):
|
||||
*
|
||||
* [ Slot 0 Stride: 12 bytes ]
|
||||
* |-------POSITION--------|
|
||||
* |------ BONE_WEIGHTS (Float32x4 = 16b) -----| <-- OVERFLOWS STRIDE!
|
||||
*
|
||||
* FIX: We alias unused attributes into Slot 0 as a 4-byte format (Float32 or Uint32).
|
||||
*
|
||||
* [ Slot 0 Stride: 12 bytes ]
|
||||
* |-------POSITION--------|
|
||||
* |-BONE-| <-- (Float32 = 4b) Safely fits inside the 12-byte stride!
|
||||
*
|
||||
* WebGPU safely promotes the 4-byte Float32 into a WGSL vec4<f32> as (x, 0.0, 0.0, 1.0).
|
||||
*/
|
||||
for (uint32_t attributeIndex = 0; attributeIndex < attributes.size(); ++attributeIndex) {
|
||||
auto attribute = attributes[attributeIndex];
|
||||
wgpu::VertexFormat vertexFormat;
|
||||
|
||||
if (attribute.buffer == Attribute::BUFFER_UNUSED) {
|
||||
if (!hasDummy) {
|
||||
continue;
|
||||
}
|
||||
// HACK: Re-use the dummy buffer for disabled attributes to satisfy WebGPU validation.
|
||||
// Filament's shaders expect vec4 or uvec4. We provide a dummy format.
|
||||
const bool isInteger = attribute.flags & Attribute::FLAG_INTEGER_TARGET;
|
||||
vertexFormat = isInteger ? wgpu::VertexFormat::Uint8x4 : wgpu::VertexFormat::Unorm8x4;
|
||||
attribute = dummyAttribute;
|
||||
} else {
|
||||
const bool isInteger = attribute.flags & Attribute::FLAG_INTEGER_TARGET;
|
||||
const bool isNormalized = attribute.flags & Attribute::FLAG_NORMALIZED;
|
||||
vertexFormat = getVertexFormat(attribute.type, isNormalized, isInteger);
|
||||
}
|
||||
|
||||
uint8_t existingSlot = INVALID_SLOT_INDEX;
|
||||
for (uint32_t slot = 0; slot < currentWebGPUSlotIndex; slot++) {
|
||||
WebGPUVertexBufferInfo::WebGPUSlotBindingInfo const& info =
|
||||
outWebGPUSlotBindingInfos[slot];
|
||||
// We consider attributes to be in the same slot/layout only if they belong to the
|
||||
// same buffer and are interleaved; they cannot belong to separate partitions in the
|
||||
// same buffer, for example.
|
||||
// For the attributes to be interleaved, the stride must match (among other things).
|
||||
// The attribute offset being less than the slot's/layout's buffer offset indicates
|
||||
// that it is in a separate partition before this slot/layout, thus not part of it.
|
||||
// The difference from the attribute's offset and this slot's/layout's buffer offset
|
||||
// being greater than the stride indicates it is in a separate partition after this
|
||||
// slot/layout, thus not part of it.
|
||||
if (info.sourceBufferIndex == attribute.buffer && info.stride == attribute.stride &&
|
||||
attribute.offset >= info.bufferOffset &&
|
||||
((attribute.offset - info.bufferOffset) < attribute.stride)) {
|
||||
@@ -269,26 +300,18 @@ void createBufferLayoutsBindingSlotsAndAttributeInfos(AttributeArray const& attr
|
||||
}
|
||||
}
|
||||
if (existingSlot == INVALID_SLOT_INDEX) {
|
||||
// New combination, use a new WebGPU slot
|
||||
FILAMENT_CHECK_PRECONDITION(currentWebGPUSlotIndex < MAX_VERTEX_BUFFER_COUNT &&
|
||||
currentWebGPUSlotIndex < deviceMaxVertexBuffers)
|
||||
<< "Number of vertex buffer layouts must not exceed MAX_VERTEX_BUFFER_COUNT ("
|
||||
<< MAX_VERTEX_BUFFER_COUNT << ") or the device limit ("
|
||||
<< deviceMaxVertexBuffers << ")";
|
||||
existingSlot = currentWebGPUSlotIndex++;
|
||||
outWebGPUSlotBindingInfos.push_back({
|
||||
.sourceBufferIndex = attribute.buffer,
|
||||
outWebGPUSlotBindingInfos.push_back({ .sourceBufferIndex = attribute.buffer,
|
||||
.bufferOffset = attribute.offset,
|
||||
.stride = attribute.stride });
|
||||
// we need to have a vertex buffer layout for each slot
|
||||
outVertexBufferLayouts.push_back({
|
||||
.stepMode = wgpu::VertexStepMode::Vertex,
|
||||
.arrayStride = attribute.stride
|
||||
// we do not know attributeCount or attributes at this time. We get those
|
||||
// in a subsequent pass over the attributeInfos we collect in this loop.
|
||||
});
|
||||
outVertexBufferLayouts.push_back(
|
||||
{ .stepMode = wgpu::VertexStepMode::Vertex, .arrayStride = attribute.stride });
|
||||
}
|
||||
// we don't use a designated initializer here because certain compilers can't handle it
|
||||
outAttributeInfos[currentAttributeIndex++] = AttributeInfo(
|
||||
existingSlot,
|
||||
{
|
||||
@@ -297,9 +320,8 @@ void createBufferLayoutsBindingSlotsAndAttributeInfos(AttributeArray const& attr
|
||||
attribute.offset - outWebGPUSlotBindingInfos[existingSlot].bufferOffset,
|
||||
.shaderLocation = attributeIndex });
|
||||
}
|
||||
FILAMENT_CHECK_POSTCONDITION(currentAttributeIndex == attributeCount)
|
||||
<< "Using " << currentAttributeIndex << " attributes, but " << attributeCount
|
||||
<< " where indicated.";
|
||||
|
||||
outActualAttributeCount = currentAttributeIndex;
|
||||
outVertexBufferLayouts.shrink_to_fit();
|
||||
outWebGPUSlotBindingInfos.shrink_to_fit();
|
||||
}
|
||||
@@ -316,21 +338,21 @@ WebGPUVertexBufferInfo::WebGPUVertexBufferInfo(const uint8_t bufferCount,
|
||||
<< ") exceeds Filament's MAX_VERTEX_ATTRIBUTE_COUNT limit ("
|
||||
<< MAX_VERTEX_ATTRIBUTE_COUNT << ") and/or the device's limit ("
|
||||
<< deviceLimits.maxVertexAttributes << ")";
|
||||
mVertexAttributes.reserve(attributeCount);
|
||||
mVertexAttributes.reserve(MAX_VERTEX_ATTRIBUTE_COUNT); // Reserve max as we might add dummies
|
||||
if (attributeCount == 0) {
|
||||
mVertexBufferLayouts.resize(0);
|
||||
mWebGPUSlotBindingInfos.resize(0);
|
||||
return; // should not be possible, but being defensive. nothing to do otherwise
|
||||
}
|
||||
std::array<AttributeInfo, MAX_VERTEX_ATTRIBUTE_COUNT> attributeInfos{};
|
||||
createBufferLayoutsBindingSlotsAndAttributeInfos(attributes, attributeCount,
|
||||
deviceLimits.maxVertexBuffers, mWebGPUSlotBindingInfos, mVertexBufferLayouts,
|
||||
attributeInfos);
|
||||
uint8_t actualAttributeCount = 0;
|
||||
createBufferLayoutsBindingSlotsAndAttributeInfos(attributes, deviceLimits.maxVertexBuffers,
|
||||
mWebGPUSlotBindingInfos, mVertexBufferLayouts, attributeInfos, actualAttributeCount);
|
||||
// sort attribute infos by increasing slot (by increasing offset within each slot).
|
||||
// We do this to ensure that attributes for the same slot/layout are contiguous in
|
||||
// the vector, so the vertex buffer layout associated with these contiguous attributes
|
||||
// can directly reference them in the mVertexAttributes vector below.
|
||||
std::sort(attributeInfos.data(), attributeInfos.data() + attributeCount,
|
||||
std::sort(attributeInfos.data(), attributeInfos.data() + actualAttributeCount,
|
||||
[](AttributeInfo const& first, AttributeInfo const& second) {
|
||||
if (first.slot < second.slot) {
|
||||
return true;
|
||||
@@ -344,7 +366,7 @@ WebGPUVertexBufferInfo::WebGPUVertexBufferInfo(const uint8_t bufferCount,
|
||||
});
|
||||
// populate mVertexAttributes and update mVertexBufferLayouts to reference the correct
|
||||
// attributes in it (which will be contiguous in memory as ensured by the sorting above)...
|
||||
for (uint32_t attributeIndex = 0; attributeIndex < attributeCount; ++attributeIndex) {
|
||||
for (uint32_t attributeIndex = 0; attributeIndex < actualAttributeCount; ++attributeIndex) {
|
||||
AttributeInfo const& info = attributeInfos[attributeIndex];
|
||||
mVertexAttributes.push_back(info.attribute);
|
||||
if (mVertexBufferLayouts[info.slot].attributeCount == 0) {
|
||||
|
||||
@@ -83,6 +83,8 @@ BackendTest::~BackendTest() {
|
||||
driver->terminate();
|
||||
delete driver;
|
||||
recordFailedImages();
|
||||
|
||||
delete mPlatform;
|
||||
}
|
||||
|
||||
void BackendTest::initializeDriver() {
|
||||
|
||||
@@ -139,8 +139,10 @@ public:
|
||||
Builder& package(const void* UTILS_NONNULL payload, size_t size);
|
||||
|
||||
template<typename T>
|
||||
using is_supported_constant_parameter_t =
|
||||
MaterialInstance::is_supported_constant_parameter_t<T>;
|
||||
using is_supported_constant_parameter_t = std::enable_if_t<
|
||||
std::is_same_v<int32_t, T> ||
|
||||
std::is_same_v<float, T> ||
|
||||
std::is_same_v<bool, T>>;
|
||||
|
||||
/**
|
||||
* Specialize a constant parameter specified in the material definition with a concrete
|
||||
@@ -241,18 +243,11 @@ public:
|
||||
* for stereoscopic rendering. If an application is not planning to render in stereo, this bit
|
||||
* should be turned off to avoid unnecessary material compilations.
|
||||
*
|
||||
* Note that it is possible to override specialization constants on a per-MaterialInstance basis
|
||||
* (@see MaterialInstance::setConstant). In that case, the programs compiled by a call to
|
||||
* Material::compile() may not be reusable by that MaterialInstance. It's better to call
|
||||
* MaterialInstance::compile() in cases where you intend to override specialization constants.
|
||||
*
|
||||
* @param priority Which priority queue to use, LOW or HIGH.
|
||||
* @param variants Variants to include to the compile command.
|
||||
* @param handler Handler to dispatch the callback or nullptr for the default handler
|
||||
* @param callback callback called on the main thread when the compilation is done on
|
||||
* by backend.
|
||||
*
|
||||
* @see Material::compile
|
||||
*/
|
||||
void compile(CompilerPriorityQueue priority,
|
||||
UserVariantFilterMask variants,
|
||||
|
||||
@@ -94,12 +94,6 @@ public:
|
||||
std::is_same_v<math::mat3f, T>
|
||||
>;
|
||||
|
||||
template<typename T>
|
||||
using is_supported_constant_parameter_t = std::enable_if_t<
|
||||
std::is_same_v<int32_t, T> ||
|
||||
std::is_same_v<float, T> ||
|
||||
std::is_same_v<bool, T>>;
|
||||
|
||||
/**
|
||||
* Creates a new MaterialInstance using another MaterialInstance as a template for initialization.
|
||||
* The new MaterialInstance is an instance of the same Material of the template instance and
|
||||
@@ -282,91 +276,6 @@ public:
|
||||
return getParameter<T>(name, strlen(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides a specialization constant of this material instance.
|
||||
*
|
||||
* @tparam T The type of the constant. Must be int32_t, float, or bool.
|
||||
* @param name The name of the constant as defined in the material. Cannot be nullptr.
|
||||
* @param nameLength Length in `char` of the name parameter.
|
||||
* @param value The value of the constant.
|
||||
*
|
||||
* @see Material::Builder::constant
|
||||
*/
|
||||
template<typename T, typename = is_supported_constant_parameter_t<T>>
|
||||
void setConstant(const char* UTILS_NONNULL name, size_t nameLength, T value);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
template<typename T, typename = is_supported_constant_parameter_t<T>>
|
||||
void setConstant(StringLiteral const name, T value) {
|
||||
setConstant<T>(name.data, name.size, value);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_constant_parameter_t<T>>
|
||||
void setConstant(const char* UTILS_NONNULL name, T value) {
|
||||
setConstant<T>(name, strlen(name), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a specialization constant by name.
|
||||
*
|
||||
* @tparam T The type of the constant. Must be int32_t, float, or bool.
|
||||
* @param name The name of the constant as defined in the material. Cannot be nullptr.
|
||||
* @param nameLength Length in `char` of the name parameter.
|
||||
* @return The value of the constant.
|
||||
*/
|
||||
template<typename T, typename = is_supported_constant_parameter_t<T>>
|
||||
T getConstant(const char* UTILS_NONNULL name, size_t nameLength) const;
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_constant_parameter_t<T>>
|
||||
T getConstant(StringLiteral const name) const {
|
||||
return getConstant<T>(name.data, name.size);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_constant_parameter_t<T>>
|
||||
T getConstant(const char* UTILS_NONNULL name) const {
|
||||
return getConstant<T>(name, strlen(name));
|
||||
}
|
||||
|
||||
using CompilerPriorityQueue = backend::CompilerPriorityQueue;
|
||||
|
||||
/**
|
||||
* Asynchronously ensures that a subset of this MaterialInstance's variants are compiled.
|
||||
*
|
||||
* This function behaves identically to Material::compile(), but takes into account the
|
||||
* specific constants overridden by setConstant().
|
||||
*
|
||||
* @param priority Which priority queue to use, LOW or HIGH.
|
||||
* @param variants Variants to include to the compile command.
|
||||
* @param handler Handler to dispatch the callback or nullptr for the default handler
|
||||
* @param callback callback called on the main thread when the compilation is done on
|
||||
* by backend.
|
||||
*
|
||||
* @see Material::compile
|
||||
* @see setConstant
|
||||
*/
|
||||
void compile(CompilerPriorityQueue priority,
|
||||
UserVariantFilterMask variants,
|
||||
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
|
||||
utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>&& callback = {}) noexcept;
|
||||
|
||||
inline void compile(CompilerPriorityQueue priority,
|
||||
UserVariantFilterBit variants,
|
||||
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
|
||||
utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>&& callback = {}) noexcept {
|
||||
compile(priority, UserVariantFilterMask(variants), handler,
|
||||
std::forward<utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>>(callback));
|
||||
}
|
||||
|
||||
inline void compile(CompilerPriorityQueue priority,
|
||||
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
|
||||
utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>&& callback = {}) noexcept {
|
||||
compile(priority, UserVariantFilterBit::ALL, handler,
|
||||
std::forward<utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>>(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set-up a custom scissor rectangle; by default it is disabled.
|
||||
*
|
||||
|
||||
@@ -182,11 +182,15 @@ Program::SpecializationConstant LocalProgramCache::getConstantImpl(
|
||||
std::string_view name) const noexcept {
|
||||
assert_invariant(mMaterial != nullptr);
|
||||
|
||||
auto const& constants = mMaterial->getDefinition().specializationConstantsNameToIndex;
|
||||
auto it = constants.find(name);
|
||||
FILAMENT_CHECK_PRECONDITION(it != constants.end()) << "Constant " << name << " does not exist";
|
||||
MaterialDefinition const& definition = mMaterial->getDefinition();
|
||||
auto it = definition.specializationConstantsNameToIndex.find(name);
|
||||
if (it != definition.specializationConstantsNameToIndex.cend()) {
|
||||
return getConstantImpl(it->second + CONFIG_MAX_RESERVED_SPEC_CONSTANTS);
|
||||
}
|
||||
|
||||
return getConstantImpl(it->second + CONFIG_MAX_RESERVED_SPEC_CONSTANTS);
|
||||
CString name_cstring(name);
|
||||
PANIC_PRECONDITION("No such constant exists: %s", name_cstring.c_str());
|
||||
return {};
|
||||
}
|
||||
|
||||
void LocalProgramCache::setConstants(
|
||||
@@ -236,13 +240,6 @@ void LocalProgramCache::setConstants(
|
||||
}
|
||||
}
|
||||
|
||||
void LocalProgramCache::setConstants(
|
||||
FixedCapacityVector<Program::SpecializationConstant> constants) noexcept {
|
||||
assert_invariant(mMaterial != nullptr);
|
||||
|
||||
setConstantsImpl(std::move(constants));
|
||||
}
|
||||
|
||||
void LocalProgramCache::setConstantsImpl(
|
||||
FixedCapacityVector<Program::SpecializationConstant> constants) noexcept {
|
||||
FEngine& engine = mMaterial->getEngine();
|
||||
|
||||
@@ -119,14 +119,7 @@ public:
|
||||
std::pair<std::string_view, backend::Program::SpecializationConstant>>
|
||||
constants) noexcept;
|
||||
|
||||
// Set constants list directly.
|
||||
void setConstants(utils::FixedCapacityVector<backend::Program::SpecializationConstant>
|
||||
constants) noexcept;
|
||||
|
||||
private:
|
||||
// Apply any pending specialization constants. Invalidates programs as necessary.
|
||||
void flushConstants() const;
|
||||
|
||||
backend::Handle<backend::HwProgram> prepareProgramSlow(backend::DriverApi& driver,
|
||||
Variant const variant,
|
||||
backend::CompilerPriorityQueue const priorityQueue) const noexcept;
|
||||
|
||||
@@ -233,26 +233,6 @@ template UTILS_PUBLIC mat3f MaterialInstance::getParameter<mat3f> (const ch
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T, typename>
|
||||
void MaterialInstance::setConstant(const char* name, size_t nameLength, T value) {
|
||||
downcast(this)->setConstantImpl(std::string_view{name, nameLength}, value);
|
||||
}
|
||||
|
||||
template UTILS_PUBLIC void MaterialInstance::setConstant<int32_t>(const char* name, size_t nameLength, int32_t value);
|
||||
template UTILS_PUBLIC void MaterialInstance::setConstant<float>(const char* name, size_t nameLength, float value);
|
||||
template UTILS_PUBLIC void MaterialInstance::setConstant<bool>(const char* name, size_t nameLength, bool value);
|
||||
|
||||
template<typename T, typename>
|
||||
T MaterialInstance::getConstant(const char* name, size_t nameLength) const {
|
||||
return downcast(this)->getConstantImpl<T>(std::string_view{name, nameLength});
|
||||
}
|
||||
|
||||
template UTILS_PUBLIC int32_t MaterialInstance::getConstant<int32_t>(const char* name, size_t nameLength) const;
|
||||
template UTILS_PUBLIC float MaterialInstance::getConstant<float>(const char* name, size_t nameLength) const;
|
||||
template UTILS_PUBLIC bool MaterialInstance::getConstant<bool>(const char* name, size_t nameLength) const;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
Material const* MaterialInstance::getMaterial() const noexcept {
|
||||
return downcast(this)->getMaterial();
|
||||
}
|
||||
@@ -423,10 +403,4 @@ void MaterialInstance::commit(Engine& engine) const {
|
||||
downcast(this)->commit(downcast(engine));
|
||||
}
|
||||
|
||||
void MaterialInstance::compile(CompilerPriorityQueue const priority,
|
||||
UserVariantFilterMask const variants, CallbackHandler* handler,
|
||||
utils::Invocable<void(MaterialInstance*)>&& callback) noexcept {
|
||||
downcast(this)->compile(priority, variants, handler, std::move(callback));
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -186,10 +186,12 @@ void PostProcessManager::PostProcessMaterial::loadMaterial(FEngine& engine) cons
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
FMaterial* PostProcessManager::PostProcessMaterial::getMaterial(FEngine& engine) const noexcept {
|
||||
FMaterial* PostProcessManager::PostProcessMaterial::getMaterial(FEngine& engine,
|
||||
DriverApi& driver, Variant::type_t const variant) const noexcept {
|
||||
if (UTILS_UNLIKELY(mSize)) {
|
||||
loadMaterial(engine);
|
||||
}
|
||||
mMaterial->prepareProgram(driver, Variant{ variant }, CompilerPriorityQueue::CRITICAL);
|
||||
return mMaterial;
|
||||
}
|
||||
|
||||
@@ -247,20 +249,6 @@ void PostProcessManager::bindPerRenderableDescriptorSet(DriverApi& driver) const
|
||||
{ { 0, 0 }, driver });
|
||||
}
|
||||
|
||||
FMaterialInstance* PostProcessManager::getMaterialInstance(backend::DriverApi& driver,
|
||||
FMaterial const* ma, Variant::type_t variant) const {
|
||||
FMaterialInstance* mi = mMaterialInstanceManager.getMaterialInstance(ma);
|
||||
mi->prepareProgram(driver, Variant{ variant }, backend::CompilerPriorityQueue::CRITICAL);
|
||||
return mi;
|
||||
}
|
||||
|
||||
FMaterialInstance* PostProcessManager::getMaterialInstanceWithTag(backend::DriverApi& driver,
|
||||
FMaterial const* ma, uint32_t tag, Variant::type_t variant) const {
|
||||
FMaterialInstance* mi = mMaterialInstanceManager.getMaterialInstance(ma, tag);
|
||||
mi->prepareProgram(driver, Variant { variant }, backend::CompilerPriorityQueue::CRITICAL);
|
||||
return mi;
|
||||
}
|
||||
|
||||
UboManager* PostProcessManager::getUboManager() const noexcept {
|
||||
return mEngine.getUboManager();
|
||||
}
|
||||
@@ -480,10 +468,9 @@ void PostProcessManager::unbindAllDescriptorSets(DriverApi& driver) noexcept {
|
||||
|
||||
UTILS_NOINLINE
|
||||
PipelineState PostProcessManager::getPipelineState(
|
||||
FMaterialInstance const* const mi, Variant::type_t const variant) const noexcept {
|
||||
FMaterial const* const ma = mi->getMaterial();
|
||||
FMaterial const* const ma, Variant::type_t const variant) const noexcept {
|
||||
return {
|
||||
.program = mi->getProgram(Variant{ variant }),
|
||||
.program = ma->getProgram(Variant{ variant }),
|
||||
.vertexBufferInfo = mFullScreenQuadVbih,
|
||||
.pipelineLayout = {
|
||||
.setLayout = {
|
||||
@@ -491,7 +478,7 @@ PipelineState PostProcessManager::getPipelineState(
|
||||
mPerRenderableDslh,
|
||||
ma->getDescriptorSetLayout().getHandle()
|
||||
}},
|
||||
.rasterState = mi->getRasterState()
|
||||
.rasterState = ma->getRasterState()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -531,7 +518,8 @@ void PostProcessManager::commitAndRenderFullScreenQuad(DriverApi& driver,
|
||||
PostProcessVariant const variant) const noexcept {
|
||||
mi->commit(driver, getUboManager());
|
||||
mi->use(driver);
|
||||
PipelineState const pipeline = getPipelineState(mi, variant);
|
||||
FMaterial const* const ma = mi->getMaterial();
|
||||
PipelineState const pipeline = getPipelineState(ma, variant);
|
||||
|
||||
assert_invariant(
|
||||
((out.params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH)
|
||||
@@ -648,12 +636,12 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph
|
||||
|
||||
auto in = resources.getTexture(data.depth);
|
||||
auto& material = getPostProcessMaterial("mipmapDepth");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterialInstance* const mi = getMaterialInstance(driver, ma);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver);
|
||||
FMaterialInstance* const mi = getMaterialInstance(ma);
|
||||
// Only the depth texture is changing in the material instance (no UBO updates),
|
||||
// we do not move getMaterialInstance() inside the loop.
|
||||
|
||||
auto pipeline = getPipelineState(mi);
|
||||
auto pipeline = getPipelineState(ma);
|
||||
|
||||
// The first mip already exists, so we process n-1 lods
|
||||
for (size_t level = 0; level < levelCount - 1; level++) {
|
||||
@@ -1013,13 +1001,14 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::screenSpaceAmbientOcclusion(
|
||||
#endif
|
||||
auto& material = getPostProcessMaterial(materialName);
|
||||
|
||||
FMaterial* ma = material.getMaterial(mEngine);
|
||||
FMaterial* ma = material.getMaterial(mEngine, driver);
|
||||
ma->getPrograms().setConstants({
|
||||
{ "useVisibilityBitmasks", options.gtao.useVisibilityBitmasks },
|
||||
{ "linearThickness", options.gtao.linearThickness },
|
||||
});
|
||||
|
||||
FMaterialInstance* const mi = getMaterialInstance(driver, ma);
|
||||
ma = material.getMaterial(mEngine, driver);
|
||||
FMaterialInstance* const mi = getMaterialInstance(ma);
|
||||
|
||||
// Set AO type specific material parameters
|
||||
switch (aoType) {
|
||||
@@ -1095,7 +1084,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::screenSpaceAmbientOcclusion(
|
||||
mi->commit(driver, getUboManager());
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = getPipelineState(mi);
|
||||
auto pipeline = getPipelineState(ma);
|
||||
pipeline.rasterState.depthFunc = RasterState::DepthFunc::L;
|
||||
assert_invariant(ssao.params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH);
|
||||
renderFullScreenQuad(ssao, pipeline, driver);
|
||||
@@ -1205,8 +1194,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::bilateralBlurPass(FrameGraph
|
||||
auto& material = config.bentNormals ?
|
||||
getPostProcessMaterial("bilateralBlurBentNormals") :
|
||||
getPostProcessMaterial("bilateralBlur");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterialInstance* const mi = getMaterialInstance(driver, ma);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver);
|
||||
FMaterialInstance* const mi = getMaterialInstance(ma);
|
||||
mi->setParameter("ssao", ssao, { /* only reads level 0 */ });
|
||||
mi->setParameter("axis", axis / float2{desc.width, desc.height});
|
||||
mi->setParameter("kernel", kGaussianSamples, kGaussianCount);
|
||||
@@ -1216,7 +1205,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::bilateralBlurPass(FrameGraph
|
||||
mi->commit(driver, getUboManager());
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = getPipelineState(mi);
|
||||
auto pipeline = getPipelineState(ma);
|
||||
pipeline.rasterState.depthFunc = RasterState::DepthFunc::L;
|
||||
renderFullScreenQuad(blurred, pipeline, driver);
|
||||
unbindAllDescriptorSets(driver);
|
||||
@@ -1375,7 +1364,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::gaussianBlurPass(FrameGraph&
|
||||
"separableGaussianBlur4L"sv : "separableGaussianBlur4"sv; break;
|
||||
}
|
||||
auto const& separableGaussianBlur = getPostProcessMaterial(materialName);
|
||||
auto ma = separableGaussianBlur.getMaterial(mEngine);
|
||||
auto ma = separableGaussianBlur.getMaterial(mEngine, driver);
|
||||
|
||||
const size_t kernelStorageSize = ma->reflect("kernel")->size;
|
||||
float2 kernel[64];
|
||||
@@ -1898,10 +1887,9 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
|
||||
auto inOutCoc = resources.getTexture(data.inOutCoc);
|
||||
|
||||
auto const& material = getPostProcessMaterial("dofMipmap");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterialInstance* const mi = getMaterialInstance(driver, ma);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver);
|
||||
|
||||
auto const pipeline = getPipelineState(mi, variant);
|
||||
auto const pipeline = getPipelineState(ma, variant);
|
||||
|
||||
for (size_t level = 0 ; level < mipmapCount - 1u ; level++) {
|
||||
const float w = FTexture::valueForLevel(level, desc.width);
|
||||
@@ -1909,8 +1897,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
|
||||
auto const& out = resources.getRenderPassInfo(data.rp[level]);
|
||||
auto inColor = driver.createTextureView(inOutColor, level, 1);
|
||||
auto inCoc = driver.createTextureView(inOutCoc, level, 1);
|
||||
// FIXME: is this necessary?
|
||||
FMaterialInstance* const mi = getMaterialInstance(driver, ma);
|
||||
FMaterialInstance* const mi = getMaterialInstance(ma);
|
||||
|
||||
mi->setParameter("color", inColor, SamplerParams{
|
||||
.filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST });
|
||||
@@ -2439,9 +2426,9 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg,
|
||||
auto const& outDesc = resources.getDescriptor(data.out);
|
||||
|
||||
auto const& material = getPostProcessMaterial("bloomUpsample");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver);
|
||||
|
||||
auto pipeline = getPipelineState(getMaterialInstance(driver, ma));
|
||||
auto pipeline = getPipelineState(ma);
|
||||
pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
|
||||
pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE;
|
||||
|
||||
@@ -2449,7 +2436,7 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg,
|
||||
// Note that we wouldn't want to use the same instance for each pass since that
|
||||
// would imply using the same UBOs, which implies synchronization across the
|
||||
// passes.
|
||||
FMaterialInstance* mi = getMaterialInstance(driver, ma);
|
||||
FMaterialInstance* mi = getMaterialInstance(ma);
|
||||
auto hwDstRT = resources.getRenderPassInfo(data.outRT[i - 1]);
|
||||
hwDstRT.params.flags.discardStart = TargetBufferFlags::NONE; // b/c we'll blend
|
||||
hwDstRT.params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
@@ -2582,12 +2569,11 @@ void PostProcessManager::colorGradingSubpass(DriverApi& driver,
|
||||
PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE;
|
||||
|
||||
auto const& material = getPostProcessMaterial("colorGradingAsSubpass");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver, variant);
|
||||
// the UBO has been set and committed in colorGradingPrepareSubpass()
|
||||
FMaterialInstance const* mi =
|
||||
getMaterialInstanceWithTag(driver, ma, colorGradingConfig.translucent, variant);
|
||||
FMaterialInstance const* mi = mMaterialInstanceManager.getMaterialInstance(ma, colorGradingConfig.translucent);
|
||||
mi->use(driver);
|
||||
auto const pipeline = getPipelineState(mi, variant);
|
||||
auto const pipeline = getPipelineState(ma, variant);
|
||||
driver.nextSubpass();
|
||||
driver.scissor(mi->getScissor());
|
||||
driver.draw(pipeline, mFullScreenQuadRph, 0, 3, 1);
|
||||
@@ -2595,8 +2581,8 @@ void PostProcessManager::colorGradingSubpass(DriverApi& driver,
|
||||
|
||||
void PostProcessManager::customResolvePrepareSubpass(DriverApi& driver, CustomResolveOp const op) noexcept {
|
||||
auto const& material = getPostProcessMaterial("customResolveAsSubpass");
|
||||
auto const ma = material.getMaterial(mEngine);
|
||||
auto* const mi = getMaterialInstance(driver, ma, 0);
|
||||
auto const ma = material.getMaterial(mEngine, driver, PostProcessVariant::OPAQUE);
|
||||
auto* const mi = mMaterialInstanceManager.getMaterialInstance(ma, 0);
|
||||
mi->setParameter("direction", op == CustomResolveOp::COMPRESS ? 1.0f : -1.0f),
|
||||
mi->commit(driver, getUboManager());
|
||||
}
|
||||
@@ -2606,12 +2592,12 @@ void PostProcessManager::customResolveSubpass(DriverApi& driver) noexcept {
|
||||
bindPerRenderableDescriptorSet(driver);
|
||||
|
||||
auto const& material = getPostProcessMaterial("customResolveAsSubpass");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver);
|
||||
// the UBO has been set and committed in customResolvePrepareSubpass()
|
||||
FMaterialInstance const* mi = getMaterialInstance(driver, ma, 0);
|
||||
FMaterialInstance const* mi = mMaterialInstanceManager.getMaterialInstance(ma, 0);
|
||||
mi->use(driver);
|
||||
|
||||
auto const pipeline = getPipelineState(mi);
|
||||
auto const pipeline = getPipelineState(ma);
|
||||
driver.nextSubpass();
|
||||
driver.scissor(mi->getScissor());
|
||||
driver.draw(pipeline, mFullScreenQuadRph, 0, 3, 1);
|
||||
@@ -2647,8 +2633,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::customResolveUncompressPass(
|
||||
void PostProcessManager::clearAncillaryBuffersPrepare(DriverApi& driver,
|
||||
Variant::type_t variant) noexcept {
|
||||
auto const& material = getPostProcessMaterial("clearDepth");
|
||||
auto const ma = material.getMaterial(mEngine);
|
||||
auto const mi = getMaterialInstanceWithTag(driver, ma, 0, variant);
|
||||
auto const ma = material.getMaterial(mEngine, driver, variant);
|
||||
auto const mi = mMaterialInstanceManager.getMaterialInstance(ma, 0);
|
||||
mi->commit(driver, getUboManager());
|
||||
}
|
||||
|
||||
@@ -2663,13 +2649,13 @@ void PostProcessManager::clearAncillaryBuffers(DriverApi& driver,
|
||||
bindPerRenderableDescriptorSet(driver);
|
||||
|
||||
auto const& material = getPostProcessMaterial("clearDepth");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver, variant);
|
||||
|
||||
// the UBO has been set and committed in clearAncillaryBuffersPrepare()
|
||||
FMaterialInstance const* const mi = getMaterialInstanceWithTag(driver, ma, 0, variant);
|
||||
FMaterialInstance const* const mi = mMaterialInstanceManager.getMaterialInstance(ma, 0);
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = getPipelineState(mi, variant);
|
||||
auto pipeline = getPipelineState(ma, variant);
|
||||
pipeline.rasterState.depthFunc = RasterState::DepthFunc::A;
|
||||
|
||||
driver.scissor(mi->getScissor());
|
||||
@@ -2679,7 +2665,7 @@ void PostProcessManager::clearAncillaryBuffers(DriverApi& driver,
|
||||
void PostProcessManager::fogPrepare(DriverApi& driver) noexcept {
|
||||
// ensures the material is loaded and material instance created
|
||||
auto const& material = getPostProcessMaterial("fog");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver, PostProcessVariant::OPAQUE);
|
||||
FMaterialInstance const* mi = ma->getDefaultInstance();
|
||||
mi->commit(driver, getUboManager());
|
||||
}
|
||||
@@ -2690,11 +2676,11 @@ void PostProcessManager::fog(DriverApi& driver) noexcept {
|
||||
bindPerRenderableDescriptorSet(driver);
|
||||
|
||||
auto const& material = getPostProcessMaterial("fog");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver);
|
||||
FMaterialInstance const* mi = ma->getDefaultInstance();
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = getPipelineState(mi, Variant::NO_VARIANT);
|
||||
auto pipeline = getPipelineState(ma, Variant::NO_VARIANT);
|
||||
driver.scissor(mi->getScissor());
|
||||
driver.draw(pipeline, mFullScreenQuadRph, 0, 3, 1);
|
||||
}
|
||||
@@ -2951,7 +2937,7 @@ void PostProcessManager::TaaJitterCamera(
|
||||
void PostProcessManager::configureTemporalAntiAliasingMaterial(backend::DriverApi& driver,
|
||||
TemporalAntiAliasingOptions const& taaOptions) noexcept {
|
||||
|
||||
FMaterial* const ma = getPostProcessMaterial("taa").getMaterial(mEngine);
|
||||
FMaterial* const ma = getPostProcessMaterial("taa").getMaterial(mEngine, driver);
|
||||
ma->getPrograms().setConstants({
|
||||
{ "upscaling", taaOptions.upscaling > 1.0f },
|
||||
{ "historyReprojection", taaOptions.historyReprojection },
|
||||
@@ -2970,7 +2956,7 @@ FMaterialInstance* PostProcessManager::configureColorGradingMaterial(backend::Dr
|
||||
PostProcessMaterial const& material, FColorGrading const* colorGrading,
|
||||
ColorGradingConfig const& colorGradingConfig, VignetteOptions const& vignetteOptions,
|
||||
uint32_t const width, uint32_t const height) noexcept {
|
||||
FMaterial* ma = material.getMaterial(mEngine);
|
||||
FMaterial* ma = material.getMaterial(mEngine, driver);
|
||||
ma->getPrograms().setConstants({
|
||||
{ "isOneDimensional", colorGrading->isOneDimensional() },
|
||||
{ "isLDR", colorGrading->isLDR() },
|
||||
@@ -2979,9 +2965,8 @@ FMaterialInstance* PostProcessManager::configureColorGradingMaterial(backend::Dr
|
||||
PostProcessVariant const variant = colorGradingConfig.translucent
|
||||
? PostProcessVariant::TRANSLUCENT
|
||||
: PostProcessVariant::OPAQUE;
|
||||
ma = material.getMaterial(mEngine);
|
||||
FMaterialInstance* mi =
|
||||
getMaterialInstanceWithTag(driver, ma, colorGradingConfig.translucent, variant);
|
||||
ma = material.getMaterial(mEngine, driver, variant);
|
||||
FMaterialInstance* mi = mMaterialInstanceManager.getMaterialInstance(ma, colorGradingConfig.translucent);
|
||||
|
||||
const SamplerParams params = SamplerParams{
|
||||
.filterMag = SamplerMagFilter::LINEAR,
|
||||
@@ -3093,9 +3078,9 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
|
||||
PostProcessVariant const variant = colorGradingConfig.translucent ?
|
||||
PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE;
|
||||
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver, variant);
|
||||
|
||||
FMaterialInstance* mi = getMaterialInstance(driver, ma);
|
||||
FMaterialInstance* mi = getMaterialInstance(ma);
|
||||
mi->setParameter("color", color, SamplerParams{}); // nearest
|
||||
mi->setParameter("depth", depth, SamplerParams{}); // nearest
|
||||
mi->setParameter("history", history, SamplerParams{
|
||||
@@ -3135,7 +3120,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
|
||||
if (colorGradingConfig.asSubpass) {
|
||||
out.params.subpassMask = 1;
|
||||
}
|
||||
auto const pipeline = getPipelineState(mi, variant);
|
||||
auto const pipeline = getPipelineState(ma, variant);
|
||||
|
||||
driver.beginRenderPass(out.target, out.params);
|
||||
driver.draw(pipeline, mFullScreenQuadRph, 0, 3, 1);
|
||||
@@ -3217,7 +3202,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::rcas(
|
||||
mi->commit(driver, getUboManager());
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = getPipelineState(mi, variant);
|
||||
auto pipeline = getPipelineState(material.getMaterial(mEngine, driver), variant);
|
||||
if (mode == RcasMode::BLENDED) {
|
||||
pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
|
||||
pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE;
|
||||
@@ -3310,7 +3295,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::upscaleBilinear(FrameGraph&
|
||||
|
||||
auto out = resources.getRenderPassInfo();
|
||||
|
||||
auto pipeline = getPipelineState(mi);
|
||||
auto pipeline = getPipelineState(material.getMaterial(mEngine, driver));
|
||||
if (blended) {
|
||||
pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
|
||||
pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE;
|
||||
@@ -3524,15 +3509,15 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::upscaleFSR1(FrameGraph& fg,
|
||||
auto out = resources.getRenderPassInfo();
|
||||
|
||||
if (UTILS_UNLIKELY(twoPassesEASU)) {
|
||||
auto pipeline0 = getPipelineState(getMaterialInstance(mEngine, driver, *splitEasuMaterial));
|
||||
auto pipeline1 = getPipelineState(getMaterialInstance(mEngine, driver, *easuMaterial));
|
||||
auto pipeline0 = getPipelineState(splitEasuMaterial->getMaterial(mEngine, driver));
|
||||
auto pipeline1 = getPipelineState(easuMaterial->getMaterial(mEngine, driver));
|
||||
pipeline1.rasterState.depthFunc = SamplerCompareFunc::NE;
|
||||
driver.beginRenderPass(out.target, out.params);
|
||||
driver.draw(pipeline0, mFullScreenQuadRph, 0, 3, 1);
|
||||
driver.draw(pipeline1, mFullScreenQuadRph, 0, 3, 1);
|
||||
driver.endRenderPass();
|
||||
} else {
|
||||
auto pipeline = getPipelineState(getMaterialInstance(mEngine, driver, *easuMaterial));
|
||||
auto pipeline = getPipelineState(easuMaterial->getMaterial(mEngine, driver));
|
||||
renderFullScreenQuad(out, pipeline, driver);
|
||||
}
|
||||
unbindAllDescriptorSets(driver);
|
||||
@@ -3584,8 +3569,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::blit(FrameGraph& fg, bool co
|
||||
|
||||
PostProcessMaterial const& material =
|
||||
getPostProcessMaterial(layer ? "blitArray" : "blitLow");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
auto* mi = getMaterialInstance(driver, ma);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver);
|
||||
auto* mi = getMaterialInstance(ma);
|
||||
mi->setParameter("color", color, SamplerParams{
|
||||
.filterMag = filterMag,
|
||||
.filterMin = filterMin
|
||||
@@ -3603,7 +3588,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::blit(FrameGraph& fg, bool co
|
||||
mi->commit(driver, getUboManager());
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = getPipelineState(mi);
|
||||
auto pipeline = getPipelineState(ma);
|
||||
if (translucent) {
|
||||
pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
|
||||
pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE;
|
||||
@@ -3901,10 +3886,10 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::debugCombineArrayTexture(Fra
|
||||
// set uniforms
|
||||
|
||||
PostProcessMaterial const& material = getPostProcessMaterial("blitArray");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
FMaterial const* const ma = material.getMaterial(mEngine, driver);
|
||||
// It should be ok to not move this getMaterialInstance to inside the loop, since
|
||||
// this is a pass meant for debug.
|
||||
auto* mi = getMaterialInstance(driver, ma);
|
||||
auto* mi = getMaterialInstance(ma);
|
||||
mi->setParameter("color", color, SamplerParams{
|
||||
.filterMag = filterMag,
|
||||
.filterMin = filterMin
|
||||
@@ -3918,7 +3903,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::debugCombineArrayTexture(Fra
|
||||
mi->commit(driver, getUboManager());
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = getPipelineState(mi);
|
||||
auto pipeline = getPipelineState(ma);
|
||||
if (translucent) {
|
||||
pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
|
||||
pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE;
|
||||
|
||||
@@ -360,7 +360,13 @@ public:
|
||||
|
||||
void terminate(FEngine& engine) noexcept;
|
||||
|
||||
FMaterial* getMaterial(FEngine& engine) const noexcept;
|
||||
FMaterial* getMaterial(FEngine& engine, backend::DriverApi& driver,
|
||||
Variant::type_t variant) const noexcept;
|
||||
|
||||
FMaterial* getMaterial(FEngine& engine, backend::DriverApi& driver,
|
||||
PostProcessVariant variant = PostProcessVariant::OPAQUE) const noexcept {
|
||||
return getMaterial(engine, driver, Variant::type_t(variant));
|
||||
}
|
||||
|
||||
private:
|
||||
void loadMaterial(FEngine& engine) const noexcept;
|
||||
@@ -387,12 +393,11 @@ public:
|
||||
|
||||
void bindPerRenderableDescriptorSet(backend::DriverApi& driver) const noexcept;
|
||||
|
||||
backend::PipelineState getPipelineState(FMaterialInstance const* mi,
|
||||
Variant::type_t variant) const noexcept;
|
||||
backend::PipelineState getPipelineState(FMaterial const* ma, Variant::type_t variant) const noexcept;
|
||||
|
||||
backend::PipelineState getPipelineState(FMaterialInstance const* mi,
|
||||
PostProcessVariant variant = PostProcessVariant::OPAQUE) const noexcept {
|
||||
return getPipelineState(mi, Variant::type_t(variant));
|
||||
backend::PipelineState getPipelineState(FMaterial const* ma,
|
||||
PostProcessVariant variant = PostProcessVariant::OPAQUE) const noexcept {
|
||||
return getPipelineState(ma, Variant::type_t(variant));
|
||||
}
|
||||
|
||||
void renderFullScreenQuad(FrameGraphResources::RenderPassInfo const& out,
|
||||
@@ -422,47 +427,27 @@ public:
|
||||
|
||||
void resetForRender();
|
||||
|
||||
|
||||
MaterialInstanceManager& getMaterialInstanceManager() noexcept {
|
||||
return mMaterialInstanceManager;
|
||||
}
|
||||
|
||||
// Helper to get a MaterialInstance from a FMaterial
|
||||
// This currently just call FMaterial::getDefaultInstance().
|
||||
FMaterialInstance* getMaterialInstance(FMaterial const* ma) {
|
||||
return mMaterialInstanceManager.getMaterialInstance(ma);
|
||||
}
|
||||
|
||||
// Helper to get a MaterialInstance from a PostProcessMaterial.
|
||||
FMaterialInstance* getMaterialInstance(FEngine& engine, backend::DriverApi& driver,
|
||||
PostProcessMaterial const& material, PostProcessVariant variant = PostProcessVariant::OPAQUE) {
|
||||
FMaterial const* ma = material.getMaterial(engine, driver, variant);
|
||||
return getMaterialInstance(ma);
|
||||
}
|
||||
|
||||
static void unbindAllDescriptorSets(backend::DriverApi& driver) noexcept;
|
||||
|
||||
private:
|
||||
|
||||
// Helpers to get MaterialInstances.
|
||||
//
|
||||
// These funcions additionally ensure that the necessary shader programs are compiled via
|
||||
// prepareProgram().
|
||||
FMaterialInstance* getMaterialInstance(backend::DriverApi& driver, FMaterial const* ma,
|
||||
Variant::type_t variant) const;
|
||||
|
||||
FMaterialInstance* getMaterialInstance(backend::DriverApi& driver, FMaterial const* ma,
|
||||
PostProcessVariant variant = PostProcessVariant::OPAQUE) const {
|
||||
return getMaterialInstance(driver, ma, Variant::type_t(variant));
|
||||
}
|
||||
|
||||
FMaterialInstance* getMaterialInstance(FEngine& engine, backend::DriverApi& driver,
|
||||
PostProcessMaterial const& material,
|
||||
PostProcessVariant variant = PostProcessVariant::OPAQUE) const {
|
||||
return getMaterialInstance(driver, material.getMaterial(engine), Variant::type_t(variant));
|
||||
}
|
||||
|
||||
FMaterialInstance* getMaterialInstanceWithTag(backend::DriverApi& driver, FMaterial const* ma,
|
||||
uint32_t tag, Variant::type_t variant) const;
|
||||
|
||||
FMaterialInstance* getMaterialInstanceWithTag(backend::DriverApi& driver, FMaterial const* ma,
|
||||
uint32_t tag, PostProcessVariant variant = PostProcessVariant::OPAQUE) const {
|
||||
return getMaterialInstanceWithTag(driver, ma, tag, Variant::type_t(variant));
|
||||
}
|
||||
|
||||
FMaterialInstance* getMaterialInstanceWithTag(FEngine& engine, backend::DriverApi& driver,
|
||||
PostProcessMaterial const& material, uint32_t tag,
|
||||
PostProcessVariant variant = PostProcessVariant::OPAQUE) const {
|
||||
return getMaterialInstanceWithTag(driver, material.getMaterial(engine), tag,
|
||||
Variant::type_t(variant));
|
||||
}
|
||||
|
||||
UboManager* getUboManager() const noexcept;
|
||||
|
||||
backend::RenderPrimitiveHandle mFullScreenQuadRph;
|
||||
|
||||
@@ -243,8 +243,8 @@ void RenderPass::appendCommands(FEngine const& engine, backend::DriverApi& drive
|
||||
// This must be done from the main thread.
|
||||
for (Command const* first = curr, *last = curr + commandCount ; first != last ; ++first) {
|
||||
if (UTILS_LIKELY((first->key & CUSTOM_MASK) == uint64_t(CustomCommand::PASS))) {
|
||||
first->info.mi->prepareProgram(driver, first->info.materialVariant,
|
||||
CompilerPriorityQueue::CRITICAL);
|
||||
auto ma = first->info.mi->getMaterial();
|
||||
ma->prepareProgram(driver, first->info.materialVariant, CompilerPriorityQueue::CRITICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -426,18 +426,16 @@ void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
bool const isBlendingCommand = !hasScreenSpaceRefraction &&
|
||||
(blendingMode != BlendingMode::OPAQUE && blendingMode != BlendingMode::MASKED);
|
||||
|
||||
RasterState rasterState = mi->getRasterState();
|
||||
|
||||
uint64_t keyDraw = cmdDraw.key;
|
||||
keyDraw &= ~(PASS_MASK | BLENDING_MASK | MATERIAL_MASK);
|
||||
keyDraw |= uint64_t(hasScreenSpaceRefraction ? Pass::REFRACT : Pass::COLOR);
|
||||
keyDraw |= uint64_t(CustomCommand::PASS);
|
||||
keyDraw |= mi->getSortingKey(); // already all set-up for direct or'ing
|
||||
keyDraw |= makeField(variant.key, MATERIAL_VARIANT_KEY_MASK, MATERIAL_VARIANT_KEY_SHIFT);
|
||||
keyDraw |= makeField(rasterState.alphaToCoverage, BLENDING_MASK, BLENDING_SHIFT);
|
||||
keyDraw |= makeField(ma->getRasterState().alphaToCoverage, BLENDING_MASK, BLENDING_SHIFT);
|
||||
|
||||
cmdDraw.key = isBlendingCommand ? keyBlending : keyDraw;
|
||||
cmdDraw.info.rasterState = rasterState;
|
||||
cmdDraw.info.rasterState = ma->getRasterState();
|
||||
|
||||
// for SSR pass, the blending mode of opaques (including MASKED) must be off
|
||||
// see Material.cpp.
|
||||
@@ -448,6 +446,10 @@ void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
BlendFunction::ZERO : cmdDraw.info.rasterState.blendFunctionDstAlpha;
|
||||
|
||||
cmdDraw.info.rasterState.inverseFrontFaces = inverseFrontFaces;
|
||||
cmdDraw.info.rasterState.culling = mi->getCullingMode();
|
||||
cmdDraw.info.rasterState.colorWrite = mi->isColorWriteEnabled();
|
||||
cmdDraw.info.rasterState.depthWrite = mi->isDepthWriteEnabled();
|
||||
cmdDraw.info.rasterState.depthFunc = mi->getDepthFunc();
|
||||
cmdDraw.info.rasterState.depthClamp = hasDepthClamp;
|
||||
cmdDraw.info.materialVariant = variant;
|
||||
// we keep "RasterState::colorWrite" to the value set by material (could be disabled)
|
||||
@@ -1088,7 +1090,8 @@ void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
|
||||
mi->use(driver, info.materialVariant);
|
||||
}
|
||||
|
||||
pipeline.program = mi->getProgram(info.materialVariant);
|
||||
assert_invariant(ma);
|
||||
pipeline.program = ma->getProgram(info.materialVariant);
|
||||
|
||||
if (UTILS_UNLIKELY(memcmp(&pipeline, ¤tPipeline, sizeof(PipelineState)) != 0)) {
|
||||
currentPipeline = pipeline;
|
||||
|
||||
@@ -636,7 +636,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::gaussianBlurSeparatedPass(
|
||||
|
||||
// get the material
|
||||
auto const& separableGaussianBlur = ppm.getPostProcessMaterial("gaussian");
|
||||
auto const ma = separableGaussianBlur.getMaterial(engine);
|
||||
auto const ma = separableGaussianBlur.getMaterial(engine, driver);
|
||||
|
||||
// Generates half of a Gaussian kernel (center + one side)
|
||||
auto generateGaussianWeights = [](std::array<float, 32>& weights,
|
||||
@@ -685,7 +685,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::gaussianBlurSeparatedPass(
|
||||
for (auto const mi : miList) {
|
||||
mi->use(driver);
|
||||
driver.scissor(mi->getScissor());
|
||||
driver.draw(ppm.getPipelineState(mi), engine.getFullScreenRenderPrimitive(), 0, 3, 1);
|
||||
driver.draw(ppm.getPipelineState(ma), engine.getFullScreenRenderPrimitive(), 0, 3, 1);
|
||||
}
|
||||
driver.endRenderPass();
|
||||
|
||||
@@ -733,12 +733,12 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::vsmMipmapPass(
|
||||
ppm.bindPerRenderableDescriptorSet(driver);
|
||||
|
||||
auto& material = ppm.getPostProcessMaterial("vsmMipmap");
|
||||
FMaterial const* const ma = material.getMaterial(engine);
|
||||
auto const mi = ppm.getMaterialInstanceManager().getMaterialInstance(ma);
|
||||
FMaterial const* const ma = material.getMaterial(engine, driver);
|
||||
|
||||
auto const pipeline = ppm.getPipelineState(mi);
|
||||
auto const pipeline = ppm.getPipelineState(ma);
|
||||
backend::Viewport const scissor = { 0, 0, dim, dim };
|
||||
|
||||
auto const mi = ppm.getMaterialInstanceManager().getMaterialInstance(ma);
|
||||
mi->setParameter("color", in, SamplerParams{
|
||||
.filterMag = SamplerMagFilter::NEAREST,
|
||||
.filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST
|
||||
|
||||
@@ -1830,7 +1830,7 @@ void FEngine::compile(
|
||||
CallbackHandler* handler,
|
||||
Invocable<void(Material*)>&& callback) {
|
||||
auto const variants = getMaterialCompileVariants(view, shadowReceiver, skinning);
|
||||
const_cast<FMaterial*>(material)->compile(priority, variants, handler, std::move(callback));
|
||||
material->compile(priority, variants, handler, std::move(callback));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -170,6 +170,8 @@ FMaterial::FMaterial(FEngine& engine, const Builder& builder, MaterialDefinition
|
||||
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
|
||||
mIsStereoSupported = driver.isStereoSupported();
|
||||
mIsParallelShaderCompileSupported = driver.isParallelShaderCompileSupported();
|
||||
mDepthPrecacheDisabled =
|
||||
driver.isWorkaroundNeeded(Workaround::DISABLE_DEPTH_PRECACHE_FOR_DEFAULT_MATERIAL);
|
||||
mDefaultMaterial = engine.getDefaultMaterial();
|
||||
@@ -238,33 +240,44 @@ filament::DescriptorSetLayout const& FMaterial::getPerViewDescriptorSetLayout(
|
||||
void FMaterial::compile(CompilerPriorityQueue const priority,
|
||||
UserVariantFilterMask variantSpec,
|
||||
CallbackHandler* handler,
|
||||
Invocable<void(Material*)>&& callback) noexcept {
|
||||
FMaterialInstance* mi = getDefaultInstance();
|
||||
if (callback) {
|
||||
mi->compile(priority, variantSpec, handler,
|
||||
[this, callback = std::move(callback)](MaterialInstance*) {
|
||||
callback(this);
|
||||
});
|
||||
} else {
|
||||
mi->compile(priority, variantSpec, handler, {});
|
||||
Invocable<void(Material*)>&& callback) const noexcept {
|
||||
DriverApi& driver = mEngine.getDriverApi();
|
||||
|
||||
// Turn off the STE variant if stereo is not supported.
|
||||
if (!mIsStereoSupported) {
|
||||
variantSpec &= ~UserVariantFilterMask(UserVariantFilterBit::STE);
|
||||
}
|
||||
|
||||
UserVariantFilterMask const variantFilter = ~variantSpec & UserVariantFilterMask(UserVariantFilterBit::ALL);
|
||||
ShaderModel const shaderModel = mEngine.getShaderModel();
|
||||
bool const isStereoSupported = mEngine.getDriverApi().isStereoSupported();
|
||||
|
||||
if (UTILS_LIKELY(mIsParallelShaderCompileSupported)) {
|
||||
for (auto const variant: mDefinition.getVariants()) {
|
||||
if (!variantFilter || variant == Variant::filterUserVariant(variant, variantFilter)) {
|
||||
if (mDefinition.hasVariant(variant, shaderModel, isStereoSupported)) {
|
||||
prepareProgram(driver, variant, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileAllPrograms(priority, handler, std::move(callback));
|
||||
}
|
||||
|
||||
void FMaterial::compile(CompilerPriorityQueue const priority,
|
||||
FixedCapacityVector<Variant> const& variants,
|
||||
CallbackHandler* handler,
|
||||
Invocable<void(Material*)>&& callback) noexcept {
|
||||
Invocable<void(Material*)>&& callback) const noexcept {
|
||||
DriverApi& driver = mEngine.getDriverApi();
|
||||
FMaterialInstance* mi = getDefaultInstance();
|
||||
|
||||
ShaderModel const shaderModel = mEngine.getShaderModel();
|
||||
bool const isStereoSupported = driver.isStereoSupported();
|
||||
bool const isParallelShaderCompileSupported = driver.isParallelShaderCompileSupported();
|
||||
|
||||
if (UTILS_LIKELY(isParallelShaderCompileSupported)) {
|
||||
if (UTILS_LIKELY(mIsParallelShaderCompileSupported)) {
|
||||
for (auto const variant : variants) {
|
||||
if (mDefinition.hasVariant(variant, shaderModel, isStereoSupported)) {
|
||||
mi->prepareProgram(driver, variant, priority);
|
||||
prepareProgram(driver, variant, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,7 +287,7 @@ void FMaterial::compile(CompilerPriorityQueue const priority,
|
||||
|
||||
void FMaterial::compileAllPrograms(CompilerPriorityQueue const priority,
|
||||
CallbackHandler* handler,
|
||||
Invocable<void(Material*)>&& callback) noexcept {
|
||||
Invocable<void(Material*)>&& callback) const noexcept {
|
||||
DriverApi& driver = mEngine.getDriverApi();
|
||||
|
||||
if (callback) {
|
||||
|
||||
@@ -106,12 +106,12 @@ public:
|
||||
void compile(CompilerPriorityQueue priority,
|
||||
UserVariantFilterMask variantSpec,
|
||||
backend::CallbackHandler* handler,
|
||||
utils::Invocable<void(Material*)>&& callback) noexcept;
|
||||
utils::Invocable<void(Material*)>&& callback) const noexcept;
|
||||
|
||||
void compile(CompilerPriorityQueue priority,
|
||||
utils::FixedCapacityVector<Variant> const& variants,
|
||||
backend::CallbackHandler* handler,
|
||||
utils::Invocable<void(Material*)>&& callback) noexcept;
|
||||
utils::Invocable<void(Material*)>&& callback) const noexcept;
|
||||
|
||||
// Creates an instance of this material, specifying the batching mode.
|
||||
FMaterialInstance* createInstance(const char* name) const noexcept;
|
||||
@@ -130,6 +130,40 @@ public:
|
||||
|
||||
FEngine& getEngine() const noexcept { return mEngine; }
|
||||
|
||||
// prepareProgram creates the program for the material's given variant at the backend level.
|
||||
// Must be called outside of backend render pass.
|
||||
// Must be called before getProgram() below.
|
||||
backend::Handle<backend::HwProgram> prepareProgram(backend::DriverApi& driver,
|
||||
Variant const variant,
|
||||
backend::CompilerPriorityQueue const priorityQueue) const noexcept {
|
||||
return mPrograms.prepareProgram(driver, variant, priorityQueue);
|
||||
}
|
||||
|
||||
// getProgram returns the backend program for the material's given variant.
|
||||
// Must be called after prepareProgram().
|
||||
[[nodiscard]]
|
||||
backend::Handle<backend::HwProgram> getProgram(Variant variant) const noexcept {
|
||||
|
||||
if (UTILS_UNLIKELY(mEngine.features.material.enable_fog_as_postprocess)) {
|
||||
// if the fog as post-process feature is enabled, we need to proceed "as-if" the material
|
||||
// didn't have the FOG variant bit.
|
||||
if (getMaterialDomain() == MaterialDomain::SURFACE) {
|
||||
BlendingMode const blendingMode = getBlendingMode();
|
||||
bool const hasScreenSpaceRefraction = getRefractionMode() == RefractionMode::SCREEN_SPACE;
|
||||
bool const isBlendingCommand = !hasScreenSpaceRefraction &&
|
||||
(blendingMode != BlendingMode::OPAQUE && blendingMode != BlendingMode::MASKED);
|
||||
if (!isBlendingCommand) {
|
||||
variant.setFog(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
updateActiveProgramsForMatdbg(variant);
|
||||
#endif
|
||||
return mPrograms.getProgram(variant);
|
||||
}
|
||||
|
||||
// MaterialInstance::use() binds descriptor sets before drawing. For shared variants,
|
||||
// however, the material instance will call useShared() to bind the default material's sets
|
||||
// instead.
|
||||
@@ -276,9 +310,6 @@ public:
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
|
||||
// Called by getProgram() to update active program list for matdbg UI.
|
||||
void updateActiveProgramsForMatdbg(Variant const variant) const noexcept;
|
||||
#endif
|
||||
|
||||
private:
|
||||
@@ -287,13 +318,15 @@ private:
|
||||
|
||||
void compileAllPrograms(CompilerPriorityQueue priority,
|
||||
backend::CallbackHandler* handler,
|
||||
utils::Invocable<void(Material*)>&& callback) noexcept;
|
||||
utils::Invocable<void(Material*)>&& callback) const noexcept;
|
||||
|
||||
MaterialDefinition const& mDefinition;
|
||||
|
||||
bool mIsDefaultMaterial = false;
|
||||
|
||||
bool mUseUboBatching = false;
|
||||
bool mIsStereoSupported = false;
|
||||
bool mIsParallelShaderCompileSupported = false;
|
||||
bool mDepthPrecacheDisabled = false;
|
||||
|
||||
FMaterial const* mDefaultMaterial = nullptr;
|
||||
@@ -308,6 +341,8 @@ private:
|
||||
mutable utils::Mutex mPendingEditsLock;
|
||||
std::unique_ptr<MaterialParser> mPendingEdits;
|
||||
std::unique_ptr<MaterialParser> mEditedMaterialParser;
|
||||
// Called by getProgram() to update active program list for matdbg UI.
|
||||
void updateActiveProgramsForMatdbg(Variant const variant) const noexcept;
|
||||
void setPendingEdits(std::unique_ptr<MaterialParser> pendingEdits) noexcept;
|
||||
bool hasPendingEdits() const noexcept;
|
||||
void latchPendingEdits() noexcept;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <filament/MaterialInstance.h>
|
||||
|
||||
#include "RenderPass.h"
|
||||
#include "MaterialParser.h"
|
||||
|
||||
#include "ds/DescriptorSetLayout.h"
|
||||
|
||||
@@ -132,7 +131,6 @@ FMaterialInstance::FMaterialInstance(FEngine& engine,
|
||||
mTextureParameters(other->mTextureParameters),
|
||||
mDescriptorSet(other->mDescriptorSet.duplicate(
|
||||
"MaterialInstance", mMaterial->getDescriptorSetLayout())),
|
||||
mPrograms(other->mPrograms),
|
||||
mPolygonOffset(other->mPolygonOffset),
|
||||
mStencilState(other->mStencilState),
|
||||
mMaskThreshold(other->mMaskThreshold),
|
||||
@@ -209,10 +207,6 @@ void FMaterialInstance::terminate(FEngine& engine) {
|
||||
if (ubHandle){
|
||||
driver.destroyBufferObject(*ubHandle);
|
||||
}
|
||||
|
||||
if (mPrograms.isInitialized()) {
|
||||
mPrograms.terminate(engine);
|
||||
}
|
||||
}
|
||||
|
||||
void FMaterialInstance::commit(FEngine& engine) const {
|
||||
@@ -270,39 +264,6 @@ void FMaterialInstance::commit(FEngine::DriverApi& driver, UboManager* uboManage
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void FMaterialInstance::setConstantImpl(std::string_view name, T value) {
|
||||
auto const& constants = mMaterial->getDefinition().specializationConstantsNameToIndex;
|
||||
auto it = constants.find(name);
|
||||
FILAMENT_CHECK_PRECONDITION(it != constants.end()) << "Constant " << name << " does not exist";
|
||||
|
||||
if (UTILS_UNLIKELY(mPendingSpecializationConstants.empty())) {
|
||||
mPendingSpecializationConstants =
|
||||
FixedCapacityVector<backend::Program::SpecializationConstant>(
|
||||
getPrograms().getSpecializationConstants());
|
||||
}
|
||||
|
||||
uint32_t id = it->second + CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
mPendingSpecializationConstants[id] = value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T FMaterialInstance::getConstantImpl(std::string_view name) const {
|
||||
auto const& constants = mMaterial->getDefinition().specializationConstantsNameToIndex;
|
||||
auto it = constants.find(name);
|
||||
FILAMENT_CHECK_PRECONDITION(it != constants.end()) << "Constant " << name << " does not exist";
|
||||
|
||||
uint32_t id = it->second + CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
|
||||
if (UTILS_UNLIKELY(!mPendingSpecializationConstants.empty())) {
|
||||
return std::get<T>(mPendingSpecializationConstants[id]);
|
||||
}
|
||||
|
||||
return getPrograms().getConstant<T>(id);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void FMaterialInstance::setParameter(std::string_view const name,
|
||||
Handle<HwTexture> texture, SamplerParams const params) {
|
||||
auto const binding = mMaterial->getSamplerBinding(name);
|
||||
@@ -422,15 +383,6 @@ void FMaterialInstance::setTransparencyMode(TransparencyMode const mode) noexcep
|
||||
mTransparencyMode = mode;
|
||||
}
|
||||
|
||||
RasterState FMaterialInstance::getRasterState() const noexcept {
|
||||
RasterState rs = mMaterial->getRasterState();
|
||||
rs.culling = mCulling;
|
||||
rs.depthWrite = mDepthWrite;
|
||||
rs.depthFunc = mDepthFunc;
|
||||
rs.colorWrite = mColorWrite;
|
||||
return rs;
|
||||
}
|
||||
|
||||
void FMaterialInstance::setDepthCulling(bool const enable) noexcept {
|
||||
mDepthFunc = enable ? RasterState::DepthFunc::GE : RasterState::DepthFunc::A;
|
||||
}
|
||||
@@ -451,51 +403,6 @@ const char* FMaterialInstance::getName() const noexcept {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void FMaterialInstance::compile(CompilerPriorityQueue const priority,
|
||||
UserVariantFilterMask variantSpec, CallbackHandler* handler,
|
||||
Invocable<void(MaterialInstance*)>&& callback) noexcept {
|
||||
FEngine& engine = mMaterial->getEngine();
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
MaterialDefinition const& definition = mMaterial->getDefinition();
|
||||
|
||||
bool const isStereoSupported = driver.isStereoSupported();
|
||||
|
||||
// Turn off the STE variant if stereo is not supported.
|
||||
if (UTILS_LIKELY(!isStereoSupported)) {
|
||||
variantSpec &= ~UserVariantFilterMask(UserVariantFilterBit::STE);
|
||||
}
|
||||
|
||||
UserVariantFilterMask const variantFilter =
|
||||
~variantSpec & UserVariantFilterMask(UserVariantFilterBit::ALL);
|
||||
ShaderModel const shaderModel = engine.getShaderModel();
|
||||
|
||||
if (UTILS_LIKELY(driver.isParallelShaderCompileSupported())) {
|
||||
for (auto const variant: definition.getVariants()) {
|
||||
if (!variantFilter || variant == Variant::filterUserVariant(variant, variantFilter)) {
|
||||
if (definition.hasVariant(variant, shaderModel, isStereoSupported)) {
|
||||
prepareProgram(driver, variant, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
struct Callback {
|
||||
Invocable<void(MaterialInstance*)> f;
|
||||
MaterialInstance* m;
|
||||
static void func(void* user) {
|
||||
auto* const c = static_cast<Callback*>(user);
|
||||
c->f(c->m);
|
||||
delete c;
|
||||
}
|
||||
};
|
||||
auto* const user = new (std::nothrow) Callback{ std::move(callback), this };
|
||||
driver.compilePrograms(priority, handler, &Callback::func, user);
|
||||
} else {
|
||||
driver.compilePrograms(priority, nullptr, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void FMaterialInstance::use(FEngine::DriverApi& driver, Variant variant) const {
|
||||
assert_invariant(mDescriptorSet.getHandle());
|
||||
assert_invariant(!isUsingUboBatching() || BufferAllocator::isValid(getAllocationId()));
|
||||
@@ -600,36 +507,4 @@ void FMaterialInstance::fixMissingSamplers() const {
|
||||
}
|
||||
}
|
||||
|
||||
LocalProgramCache const& FMaterialInstance::getPrograms() const noexcept {
|
||||
return mPrograms.isInitialized() ? mPrograms : mMaterial->getPrograms();
|
||||
}
|
||||
|
||||
void FMaterialInstance::flushSpecializationConstants() const noexcept {
|
||||
if (mPendingSpecializationConstants.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mPrograms.isInitialized()) {
|
||||
mPrograms.initializeForMaterialInstance(mMaterial->getEngine(), *mMaterial);
|
||||
}
|
||||
mPrograms.setConstants(std::move(mPendingSpecializationConstants));
|
||||
mPendingSpecializationConstants.clear();
|
||||
}
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
|
||||
void FMaterialInstance::updateActiveProgramsForMatdbg(Variant const variant) const noexcept {
|
||||
mMaterial->updateActiveProgramsForMatdbg(variant);
|
||||
}
|
||||
|
||||
#endif // FILAMENT_ENABLE_MATDBG
|
||||
|
||||
template void FMaterialInstance::setConstantImpl<int32_t>(std::string_view name, int32_t value);
|
||||
template void FMaterialInstance::setConstantImpl<float>(std::string_view name, float value);
|
||||
template void FMaterialInstance::setConstantImpl<bool>(std::string_view name, bool value);
|
||||
|
||||
template int32_t FMaterialInstance::getConstantImpl<int32_t>(std::string_view name) const;
|
||||
template float FMaterialInstance::getConstantImpl<float>(std::string_view name) const;
|
||||
template bool FMaterialInstance::getConstantImpl<bool>(std::string_view name) const;
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define TNT_FILAMENT_DETAILS_MATERIALINSTANCE_H
|
||||
|
||||
#include "downcast.h"
|
||||
#include "LocalProgramCache.h"
|
||||
|
||||
#include "UniformBuffer.h"
|
||||
|
||||
#include "ds/DescriptorSet.h"
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "details/BufferAllocator.h"
|
||||
#include "details/Engine.h"
|
||||
|
||||
#include "private/backend/DriverApi.h"
|
||||
|
||||
#include <filament/MaterialInstance.h>
|
||||
|
||||
#include <private/filament/Variant.h>
|
||||
@@ -65,7 +67,7 @@ public:
|
||||
~FMaterialInstance() noexcept;
|
||||
|
||||
void terminate(FEngine& engine);
|
||||
|
||||
|
||||
void commit(FEngine& engine) const;
|
||||
|
||||
void commit(FEngine::DriverApi& driver, UboManager* uboManager) const;
|
||||
@@ -84,32 +86,6 @@ public:
|
||||
|
||||
UniformBuffer const& getUniformBuffer() const noexcept { return mUniforms; }
|
||||
|
||||
void compile(backend::CompilerPriorityQueue priority, UserVariantFilterMask variantSpec,
|
||||
backend::CallbackHandler* handler,
|
||||
utils::Invocable<void(MaterialInstance*)>&& callback) noexcept;
|
||||
|
||||
// prepareProgram creates the program for the material's given variant at the backend level.
|
||||
// Must be called outside of backend render pass.
|
||||
// Must be called before getProgram() below.
|
||||
backend::Handle<backend::HwProgram> prepareProgram(backend::DriverApi& driver,
|
||||
Variant const variant,
|
||||
backend::CompilerPriorityQueue const priorityQueue) const noexcept {
|
||||
flushSpecializationConstants();
|
||||
return getPrograms().prepareProgram(driver, variant, priorityQueue);
|
||||
}
|
||||
|
||||
// getProgram returns the backend program for the material's given variant.
|
||||
// Must be called after prepareProgram().
|
||||
//
|
||||
// See also Material::getProgram().
|
||||
[[nodiscard]]
|
||||
backend::Handle<backend::HwProgram> getProgram(Variant const variant) const noexcept {
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
updateActiveProgramsForMatdbg(variant);
|
||||
#endif
|
||||
return getPrograms().getProgram(variant);
|
||||
}
|
||||
|
||||
void setScissor(uint32_t const left, uint32_t const bottom, uint32_t const width, uint32_t const height) noexcept {
|
||||
constexpr uint32_t maxvalu = std::numeric_limits<int32_t>::max();
|
||||
mScissorRect = { int32_t(left), int32_t(bottom),
|
||||
@@ -131,8 +107,6 @@ public:
|
||||
|
||||
bool hasScissor() const noexcept { return mHasScissor; }
|
||||
|
||||
backend::RasterState getRasterState() const noexcept;
|
||||
|
||||
backend::CullingMode getCullingMode() const noexcept { return mCulling; }
|
||||
|
||||
backend::CullingMode getShadowCullingMode() const noexcept { return mShadowCulling; }
|
||||
@@ -280,15 +254,11 @@ public:
|
||||
backend::Handle<backend::HwTexture> texture, backend::SamplerParams params);
|
||||
|
||||
using MaterialInstance::setParameter;
|
||||
using MaterialInstance::setConstant;
|
||||
|
||||
private:
|
||||
friend class FMaterial;
|
||||
friend class MaterialInstance;
|
||||
|
||||
// Cannot inline since it inspects the FMaterial class.
|
||||
LocalProgramCache const& getPrograms() const noexcept;
|
||||
|
||||
template<size_t Size>
|
||||
void setParameterUntypedImpl(std::string_view name, const void* value);
|
||||
|
||||
@@ -307,19 +277,6 @@ private:
|
||||
template<typename T>
|
||||
T getParameterImpl(std::string_view name) const;
|
||||
|
||||
template<typename T>
|
||||
void setConstantImpl(std::string_view name, T value);
|
||||
|
||||
template<typename T>
|
||||
T getConstantImpl(std::string_view name) const;
|
||||
|
||||
void flushSpecializationConstants() const noexcept;
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
// Called by getProgram() to update active program list for matdbg UI.
|
||||
void updateActiveProgramsForMatdbg(Variant const variant) const noexcept;
|
||||
#endif
|
||||
|
||||
// keep these grouped, they're accessed together in the render-loop
|
||||
FMaterial const* mMaterial = nullptr;
|
||||
|
||||
@@ -334,11 +291,6 @@ private:
|
||||
mutable DescriptorSet mDescriptorSet;
|
||||
UniformBuffer mUniforms;
|
||||
|
||||
// HACK: Mutable so that prepareProgram() can update specialization constants.
|
||||
mutable LocalProgramCache mPrograms;
|
||||
mutable utils::FixedCapacityVector<backend::Program::SpecializationConstant>
|
||||
mPendingSpecializationConstants;
|
||||
|
||||
backend::PolygonOffset mPolygonOffset{};
|
||||
backend::StencilState mStencilState{};
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Material.h>
|
||||
#include <filament/MaterialInstance.h>
|
||||
|
||||
#include "filament_test_resources.h"
|
||||
|
||||
@@ -168,52 +167,3 @@ TEST(Material, MaterialSettingInvalidApiLevelReturnsAnInvalidPackage) {
|
||||
|
||||
Engine::destroy(engine);
|
||||
}
|
||||
|
||||
TEST(MaterialInstanceTest, SetConstant) {
|
||||
Engine* engine = Engine::create(Engine::Backend::NOOP);
|
||||
|
||||
std::string shaderCode(R"(
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
material.baseColor = vec4(1.0);
|
||||
}
|
||||
)");
|
||||
|
||||
filamat::MaterialBuilder builder;
|
||||
builder.init();
|
||||
builder.name("MaterialInstanceTest");
|
||||
builder.material(shaderCode.c_str());
|
||||
builder.constant("myFloat", filamat::MaterialBuilder::ConstantType::FLOAT, 1.0f);
|
||||
builder.constant("myInt", filamat::MaterialBuilder::ConstantType::INT, 2);
|
||||
builder.constant("myBool", filamat::MaterialBuilder::ConstantType::BOOL, false);
|
||||
|
||||
filamat::Package result = builder.build(engine->getJobSystem());
|
||||
ASSERT_TRUE(result.isValid());
|
||||
|
||||
Material* material = Material::Builder()
|
||||
.package(result.getData(), result.getSize())
|
||||
.build(*engine);
|
||||
ASSERT_NE(material, nullptr);
|
||||
|
||||
MaterialInstance* instance = material->createInstance();
|
||||
ASSERT_NE(instance, nullptr);
|
||||
|
||||
// Verify default values
|
||||
EXPECT_EQ(instance->getConstant<float>("myFloat"), 1.0f);
|
||||
EXPECT_EQ(instance->getConstant<int32_t>("myInt"), 2);
|
||||
EXPECT_EQ(instance->getConstant<bool>("myBool"), false);
|
||||
|
||||
// Set new values
|
||||
instance->setConstant("myFloat", 3.0f);
|
||||
instance->setConstant("myInt", 4);
|
||||
instance->setConstant("myBool", true);
|
||||
|
||||
// Verify new values
|
||||
EXPECT_EQ(instance->getConstant<float>("myFloat"), 3.0f);
|
||||
EXPECT_EQ(instance->getConstant<int32_t>("myInt"), 4);
|
||||
EXPECT_EQ(instance->getConstant<bool>("myBool"), true);
|
||||
|
||||
engine->destroy(instance);
|
||||
engine->destroy(material);
|
||||
Engine::destroy(engine);
|
||||
}
|
||||
|
||||
@@ -881,14 +881,6 @@ utils::io::sstream& CodeGenerator::generateSpecializationConstant(utils::io::sst
|
||||
|
||||
static const char* types[] = { "int", "float", "bool" };
|
||||
|
||||
// Spec constants aren't fully supported in Tint,
|
||||
// workaround until https://issues.chromium.org/issues/42250586 is resolved
|
||||
if (mTargetApi == TargetApi::WEBGPU) {
|
||||
std::string const variableName = "FILAMENT_SPEC_CONST_" + std::to_string(id) + "_" + name;
|
||||
out << " const " << types[value.index()] << " " << variableName << " = " << constantString << ";\n";
|
||||
out << types[value.index()] << " " << name << " = " << variableName << ";\n";
|
||||
return out;
|
||||
}
|
||||
if (mTargetLanguage == MaterialBuilderBase::TargetLanguage::SPIRV) {
|
||||
out << "layout (constant_id = " << id << ") const "
|
||||
<< types[value.index()] << " " << name << " = " << constantString << ";\n";
|
||||
|
||||
+18
-4
@@ -14,6 +14,7 @@ if [ ! -d "${PROJECT_ROOT_DIR}/mesa/out" ]; then
|
||||
fi
|
||||
|
||||
BACKEND_TEST_TARGET=''
|
||||
ASAN_FLAG=''
|
||||
|
||||
# Set environment variables to use Mesa drivers.
|
||||
os_name=$(uname -s)
|
||||
@@ -27,15 +28,18 @@ if [[ "$os_name" == "Linux" ]]; then
|
||||
export VK_ICD_FILENAMES="${PROJECT_ROOT_DIR}/mesa/out/share/vulkan/icd.d/lvp_icd.x86_64.json"
|
||||
fi
|
||||
BACKEND_TEST_TARGET=backend_test_linux
|
||||
ASAN_FLAG="-b"
|
||||
elif [[ "$os_name" == "Darwin" ]]; then
|
||||
export DYLD_LIBRARY_PATH="${PROJECT_ROOT_DIR}/mesa/out/lib"
|
||||
export VK_ICD_FILENAMES="${PROJECT_ROOT_DIR}/mesa/out/share/vulkan/icd.d/lvp_icd.aarch64.json"
|
||||
BACKEND_TEST_TARGET=backend_test_mac
|
||||
# asan is too slow for macOs build of the backend test
|
||||
ASAN_FLAG=""
|
||||
fi
|
||||
|
||||
# Build backend_test_mac
|
||||
echo "Building backend_test_mac..."
|
||||
"${PROJECT_ROOT_DIR}/build.sh" -W -p desktop -X "${PROJECT_ROOT_DIR}/mesa" debug ${BACKEND_TEST_TARGET}
|
||||
# Build backend test
|
||||
echo "Building ${BACKEND_TEST_TARGET}..."
|
||||
"${PROJECT_ROOT_DIR}/build.sh" ${ASAN_FLAG} -W -y release -p desktop -X "${PROJECT_ROOT_DIR}/mesa" debug ${BACKEND_TEST_TARGET}
|
||||
|
||||
set +e
|
||||
|
||||
@@ -51,10 +55,20 @@ do
|
||||
fi
|
||||
done
|
||||
|
||||
# Mesa OSMesa is known to leak part of the context.
|
||||
LSAN_CMD_PREFIX=""
|
||||
if [[ "${ASAN_FLAG}" == "-b" ]]; then
|
||||
echo "leak:PlatformOSMesa.cpp" > /tmp/leak_skip.txt
|
||||
LSAN_CMD_PREFIX="LSAN_OPTIONS=suppressions=/tmp/leak_skip.txt"
|
||||
fi
|
||||
|
||||
FINAL_RESULT=0
|
||||
for BACKEND in ${BACKENDS[@]}; do
|
||||
echo "----- ${BACKEND} backend test -----"
|
||||
${PROJECT_ROOT_DIR}/out/cmake-debug/filament/backend/${BACKEND_TEST_TARGET} -a ${BACKEND} --ci --headless_only ${GTEST_FILTER_ARG}
|
||||
|
||||
${LSAN_CMD_PREFIX} ${PROJECT_ROOT_DIR}/out/cmake-debug/filament/backend/${BACKEND_TEST_TARGET} \
|
||||
-a ${BACKEND} --ci --headless_only ${GTEST_FILTER_ARG}
|
||||
|
||||
RESULT=$(echo $?)
|
||||
if [ ${RESULT} -gt 0 ]; then
|
||||
echo "----- Error: backend ${BACKEND} test failed with result ${RESULT} -----"
|
||||
|
||||
+13
-1
@@ -302,7 +302,19 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#if (defined(__clang__) && !defined(_WIN32)) || \
|
||||
(defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \
|
||||
(defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__))
|
||||
#define ABSL_HAVE_INTRINSIC_INT128 1
|
||||
|
||||
// Disable int128 instrinsic on arm when asan is enabled
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
#if defined(__has_feature) || defined(__SANITIZE_ADDRESS__)
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#define ABSL_ASAN_ON_ARM_DISABLE_INT128 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ABSL_ASAN_ON_ARM_DISABLE_INT128
|
||||
#define ABSL_HAVE_INTRINSIC_INT128 1
|
||||
#endif
|
||||
|
||||
#elif defined(__CUDACC__)
|
||||
// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a
|
||||
// string explaining that it has been removed starting with CUDA 9. We use
|
||||
|
||||
Vendored
+10
@@ -32,3 +32,13 @@ This folder previously last updated as follows:
|
||||
rsync -r abseil_new/ abseil/ --delete --exclude tnt
|
||||
rm -rf master.zip abseil_new
|
||||
git add abseil ; git status
|
||||
|
||||
## Custom Changes
|
||||
|
||||
A custom patch has been applied to fix compilation on ARM architectures when AddressSanitizer (ASAN) is enabled (specifically regarding `ABSL_HAVE_INTRINSIC_INT128`).
|
||||
|
||||
If you update the `abseil` folder, you may need to re-apply the patch. You can do so by running the following command from the repository root:
|
||||
|
||||
```shell
|
||||
git apply third_party/abseil/tnt/asan_arm_int128.diff
|
||||
```
|
||||
|
||||
Vendored
+1
-2
@@ -52,8 +52,6 @@ if (ANDROID AND FILAMENT_BUILD_FILAMAT)
|
||||
tint_lang_spirv_intrinsic
|
||||
tint_lang_spirv_ir
|
||||
tint_lang_spirv_reader
|
||||
tint_lang_spirv_reader_ast_lower
|
||||
tint_lang_spirv_reader_ast_parser
|
||||
tint_lang_spirv_reader_common
|
||||
tint_lang_spirv_reader_lower
|
||||
tint_lang_spirv_reader_parser
|
||||
@@ -77,6 +75,7 @@ if (ANDROID AND FILAMENT_BUILD_FILAMAT)
|
||||
tint_utils_rtti
|
||||
tint_utils_strconv
|
||||
tint_utils_symbol
|
||||
tint_utils_system
|
||||
tint_utils_text
|
||||
tint_utils_text_generator
|
||||
)
|
||||
|
||||
@@ -4,7 +4,8 @@ material {
|
||||
color
|
||||
],
|
||||
shadingModel : unlit,
|
||||
culling : none
|
||||
culling : none,
|
||||
featureLevel: 0
|
||||
}
|
||||
|
||||
fragment {
|
||||
|
||||
@@ -31,6 +31,7 @@ set(COPTS "${COPTS} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0")
|
||||
set(LOPTS "${LOPTS} --bind")
|
||||
set(LOPTS "${LOPTS} -s ALLOW_MEMORY_GROWTH=1")
|
||||
set(LOPTS "${LOPTS} -s EXPORTED_FUNCTIONS=['_malloc','_free']")
|
||||
set(LOPTS "${LOPTS} -s EXPORTED_RUNTIME_METHODS=['HEAP8','HEAP16','HEAP32','HEAPU8','HEAPU16','HEAPU32','HEAPF32','HEAPF64']")
|
||||
set(LOPTS "${LOPTS} -s MODULARIZE=1")
|
||||
set(LOPTS "${LOPTS} -s EXPORT_NAME=Filament")
|
||||
set(LOPTS "${LOPTS} -s USE_WEBGL2=1")
|
||||
|
||||
Reference in New Issue
Block a user