From 0a2fa36d5a2c0760f61adf0e3412c8e2f11cfbcd Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Fri, 9 Jul 2021 17:32:08 -0700 Subject: [PATCH] API CHANGE: honor user-defined precision, rename SamplerPrecision. (#4287) * API CHANGE: honor user-defined precision, rename SamplerPrecision. matc now honors 'precision' on non-samplers in mat files, and the filamat API now allows clients to specify precision for non-samplers. This involved flattening a union that is internal to filamat. * MaterialBuilder: Add Java bindings for precision. --- RELEASE_NOTES.md | 2 +- .../src/main/cpp/MaterialBuilder.cpp | 13 ++-- .../filament/filamat/MaterialBuilder.java | 29 +++++++-- docs/Materials.md.html | 10 ++-- libs/filamat/include/filamat/Enums.h | 4 +- .../filamat/include/filamat/MaterialBuilder.h | 59 ++++++++++--------- libs/filamat/src/Enums.cpp | 12 ++-- libs/filamat/src/MaterialBuilder.cpp | 36 +++++------ tools/matc/src/matc/ParametersProcessor.cpp | 21 ++++--- 9 files changed, 107 insertions(+), 79 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 972b08aca2..c3c828b5ee 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -3,7 +3,7 @@ This file contains one line summaries of commits that are worthy of mentioning in release notes. A new header is inserted each time a *tag* is created. -## v1.10.8 (currently main branch) +## v1.11.0 (currently main branch) - engine: Added support for transparent shadows. Add `transparentShadow : true` in the material file. - java: Removed support for Java desktop targets (macOS, Linux, and Windows) [⚠️ **API Change**]. diff --git a/android/filamat-android/src/main/cpp/MaterialBuilder.cpp b/android/filamat-android/src/main/cpp/MaterialBuilder.cpp index aba81d937f..86f3e87515 100644 --- a/android/filamat-android/src/main/cpp/MaterialBuilder.cpp +++ b/android/filamat-android/src/main/cpp/MaterialBuilder.cpp @@ -123,19 +123,22 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderInterpo extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderUniformParameter( - JNIEnv* env, jclass, jlong nativeBuilder, jint uniformType, jstring name_) { + JNIEnv* env, jclass, jlong nativeBuilder, jint uniformType, jstring name_, jint precision) { auto builder = (MaterialBuilder*) nativeBuilder; const char* name = env->GetStringUTFChars(name_, nullptr); - builder->parameter((MaterialBuilder::UniformType) uniformType, name); + builder->parameter((MaterialBuilder::UniformType) uniformType, name, + (MaterialBuilder::ParameterPrecision) precision); env->ReleaseStringUTFChars(name_, name); } extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderUniformParameterArray( - JNIEnv* env, jclass, jlong nativeBuilder, jint uniformType, jint size, jstring name_) { + JNIEnv* env, jclass, jlong nativeBuilder, jint uniformType, jint size, jstring name_, + jint precision) { auto builder = (MaterialBuilder*) nativeBuilder; const char* name = env->GetStringUTFChars(name_, nullptr); - builder->parameter((MaterialBuilder::UniformType) uniformType, (size_t) size, name); + builder->parameter((MaterialBuilder::UniformType) uniformType, (size_t) size, name, + (MaterialBuilder::ParameterPrecision) precision); env->ReleaseStringUTFChars(name_, name); } @@ -146,7 +149,7 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderSampler auto builder = (MaterialBuilder*) nativeBuilder; const char* name = env->GetStringUTFChars(name_, nullptr); builder->parameter((MaterialBuilder::SamplerType) samplerType, - (MaterialBuilder::SamplerFormat) format, (MaterialBuilder::SamplerPrecision) precision, + (MaterialBuilder::SamplerFormat) format, (MaterialBuilder::ParameterPrecision) precision, name); env->ReleaseStringUTFChars(name_, name); } diff --git a/android/filamat-android/src/main/java/com/google/android/filament/filamat/MaterialBuilder.java b/android/filamat-android/src/main/java/com/google/android/filament/filamat/MaterialBuilder.java index 7190e0bc37..81c063d7f1 100644 --- a/android/filamat-android/src/main/java/com/google/android/filament/filamat/MaterialBuilder.java +++ b/android/filamat-android/src/main/java/com/google/android/filament/filamat/MaterialBuilder.java @@ -91,7 +91,7 @@ public class MaterialBuilder { SHADOW } - public enum SamplerPrecision { + public enum ParameterPrecision { LOW, MEDIUM, HIGH, @@ -247,19 +247,36 @@ public class MaterialBuilder { @NonNull public MaterialBuilder uniformParameter(@NonNull UniformType type, String name) { - nMaterialBuilderUniformParameter(mNativeObject, type.ordinal(), name); + nMaterialBuilderUniformParameter(mNativeObject, type.ordinal(), name, + ParameterPrecision.DEFAULT.ordinal()); + return this; + } + + @NonNull + public MaterialBuilder uniformParameter(@NonNull UniformType type, String name, + ParameterPrecision precision) { + nMaterialBuilderUniformParameter(mNativeObject, type.ordinal(), name, precision.ordinal()); return this; } @NonNull public MaterialBuilder uniformParameterArray(@NonNull UniformType type, int size, String name) { - nMaterialBuilderUniformParameterArray(mNativeObject, type.ordinal(), size, name); + nMaterialBuilderUniformParameterArray(mNativeObject, type.ordinal(), size, name, + ParameterPrecision.DEFAULT.ordinal()); + return this; + } + + @NonNull + public MaterialBuilder uniformParameterArray(@NonNull UniformType type, int size, String name, + ParameterPrecision precision) { + nMaterialBuilderUniformParameterArray(mNativeObject, type.ordinal(), size, name, + precision.ordinal()); return this; } @NonNull public MaterialBuilder samplerParameter(@NonNull SamplerType type, SamplerFormat format, - SamplerPrecision precision, String name) { + ParameterPrecision precision, String name) { nMaterialBuilderSamplerParameter( mNativeObject, type.ordinal(), format.ordinal(), precision.ordinal(), name); return this; @@ -535,9 +552,9 @@ public class MaterialBuilder { private static native void nMaterialBuilderShading(long nativeBuilder, int shading); private static native void nMaterialBuilderInterpolation(long nativeBuilder, int interpolation); private static native void nMaterialBuilderUniformParameter(long nativeBuilder, int type, - String name); + String name, int precision); private static native void nMaterialBuilderUniformParameterArray(long nativeBuilder, int type, - int size, String name); + int size, String name, int precision); private static native void nMaterialBuilderSamplerParameter(long nativeBuilder, int type, int format, int precision, String name); private static native void nMaterialBuilderVariable(long nativeBuilder, int variable, diff --git a/docs/Materials.md.html b/docs/Materials.md.html index 3ba4bb430d..a41e1a2c87 100644 --- a/docs/Materials.md.html +++ b/docs/Materials.md.html @@ -959,7 +959,9 @@ Type Value : Each entry is an object with the properties `name` and `type`, both of `string` type. The - name must be a valid GLSL identifier. The type must be one of the types described in + name must be a valid GLSL identifier. Entries also have an optional `precision`, which can be + one of `default` (best precision for the platform, typically `high` on desktop, `medium` on + mobile), `low`, `medium`, `high`. The type must be one of the types described in table [materialParamsTypes]. Type | Description @@ -988,10 +990,8 @@ samplerCubemap | Cubemap texture [Table [materialParamsTypes]: Material parameter types] Samplers -: Sampler types can also specify a `format` (defaults to `float`) and a `precision` (defaults - to `default`). The format can be one of `int`, `float`. The precision can be one of `default` - (best precision for the platform, typically `high` on desktop, `medium` on mobile), - `low`, `medium`, `high`. +: Sampler types can also specify a `format` which can be either `int` or `float` (defaults to + `float`). Arrays : A parameter can define an array of values by appending `[size]` after the type name, where diff --git a/libs/filamat/include/filamat/Enums.h b/libs/filamat/include/filamat/Enums.h index cb0600ba7a..ea626e814a 100644 --- a/libs/filamat/include/filamat/Enums.h +++ b/libs/filamat/include/filamat/Enums.h @@ -30,7 +30,7 @@ using UniformType = MaterialBuilder::UniformType; using SamplerType = MaterialBuilder::SamplerType; using SubpassType = MaterialBuilder::SubpassType; using SamplerFormat = MaterialBuilder::SamplerFormat; -using SamplerPrecision = MaterialBuilder::SamplerPrecision; +using ParameterPrecision = MaterialBuilder::ParameterPrecision; using OutputTarget = MaterialBuilder::OutputTarget; using OutputQualifier = MaterialBuilder::VariableQualifier; using OutputType = MaterialBuilder::OutputType; @@ -73,7 +73,7 @@ private: static std::unordered_map mStringToSamplerType; static std::unordered_map mStringToSubpassType; static std::unordered_map mStringToSamplerFormat; - static std::unordered_map mStringToSamplerPrecision; + static std::unordered_map mStringToSamplerPrecision; static std::unordered_map mStringToOutputTarget; static std::unordered_map mStringToOutputQualifier; static std::unordered_map mStringToOutputType; diff --git a/libs/filamat/include/filamat/MaterialBuilder.h b/libs/filamat/include/filamat/MaterialBuilder.h index a194cfff23..e925f7d369 100644 --- a/libs/filamat/include/filamat/MaterialBuilder.h +++ b/libs/filamat/include/filamat/MaterialBuilder.h @@ -203,7 +203,7 @@ public: using SamplerType = filament::backend::SamplerType; using SubpassType = filament::backend::SubpassType; using SamplerFormat = filament::backend::SamplerFormat; - using SamplerPrecision = filament::backend::Precision; + using ParameterPrecision = filament::backend::Precision; using CullingMode = filament::backend::CullingMode; enum class VariableQualifier : uint8_t { @@ -244,10 +244,12 @@ public: MaterialBuilder& interpolation(Interpolation interpolation) noexcept; //! Add a parameter (i.e., a uniform) to this material. - MaterialBuilder& parameter(UniformType type, const char* name) noexcept; + MaterialBuilder& parameter(UniformType type, const char* name, + ParameterPrecision precision = ParameterPrecision::DEFAULT) noexcept; //! Add a parameter array to this material. - MaterialBuilder& parameter(UniformType type, size_t size, const char* name) noexcept; + MaterialBuilder& parameter(UniformType type, size_t size, const char* name, + ParameterPrecision precision = ParameterPrecision::DEFAULT) noexcept; /** * Add a sampler parameter to this material. @@ -255,14 +257,14 @@ public: * When SamplerType::SAMPLER_EXTERNAL is specifed, format and precision are ignored. */ MaterialBuilder& parameter(SamplerType samplerType, SamplerFormat format, - SamplerPrecision precision, const char* name) noexcept; - /// @copydoc parameter(SamplerType, SamplerFormat, SamplerPrecision, const char*) + ParameterPrecision precision, const char* name) noexcept; + /// @copydoc parameter(SamplerType, SamplerFormat, ParameterPrecision, const char*) MaterialBuilder& parameter(SamplerType samplerType, SamplerFormat format, const char* name) noexcept; - /// @copydoc parameter(SamplerType, SamplerFormat, SamplerPrecision, const char*) - MaterialBuilder& parameter(SamplerType samplerType, SamplerPrecision precision, + /// @copydoc parameter(SamplerType, SamplerFormat, ParameterPrecision, const char*) + MaterialBuilder& parameter(SamplerType samplerType, ParameterPrecision precision, const char* name) noexcept; - /// @copydoc parameter(SamplerType, SamplerFormat, SamplerPrecision, const char*) + /// @copydoc parameter(SamplerType, SamplerFormat, ParameterPrecision, const char*) MaterialBuilder& parameter(SamplerType samplerType, const char* name) noexcept; //! Custom variables (all float4). @@ -525,37 +527,36 @@ public: /** * Add a subpass parameter to this material. */ - MaterialBuilder& parameter(SubpassType subpassType, SamplerFormat format, SamplerPrecision + MaterialBuilder& parameter(SubpassType subpassType, SamplerFormat format, ParameterPrecision precision, const char* name) noexcept; MaterialBuilder& parameter(SubpassType subpassType, SamplerFormat format, const char* name) noexcept; - MaterialBuilder& parameter(SubpassType subpassType, SamplerPrecision precision, + MaterialBuilder& parameter(SubpassType subpassType, ParameterPrecision precision, const char* name) noexcept; MaterialBuilder& parameter(SubpassType subpassType, const char* name) noexcept; struct Parameter { Parameter() noexcept : parameterType(INVALID) {} - Parameter(const char* paramName, SamplerType t, SamplerFormat f, SamplerPrecision p) - : name(paramName), size(1), samplerType(t), format(f), precision(p), - parameterType(SAMPLER) { } - Parameter(const char* paramName, UniformType t, size_t typeSize) - : name(paramName), size(typeSize), uniformType(t), parameterType(UNIFORM) { } - Parameter(const char* paramName, SubpassType t, SamplerFormat f, SamplerPrecision p) - : name(paramName), size(1), subpassType(t), format(f), precision(p), - parameterType(SUBPASS) { } + + // Sampler + Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p) + : name(paramName), size(1), precision(p), samplerType(t), format(f), parameterType(SAMPLER) { } + + // Uniform + Parameter(const char* paramName, UniformType t, size_t typeSize, ParameterPrecision p) + : name(paramName), size(typeSize), uniformType(t), precision(p), parameterType(UNIFORM) { } + + // Subpass + Parameter(const char* paramName, SubpassType t, SamplerFormat f, ParameterPrecision p) + : name(paramName), size(1), precision(p), subpassType(t), format(f), parameterType(SUBPASS) { } + utils::CString name; size_t size; - union { - UniformType uniformType; - struct { - union { - SamplerType samplerType; - SubpassType subpassType; - }; - SamplerFormat format; - SamplerPrecision precision; - }; - }; + UniformType uniformType; + ParameterPrecision precision; + SamplerType samplerType; + SubpassType subpassType; + SamplerFormat format; enum { INVALID, UNIFORM, diff --git a/libs/filamat/src/Enums.cpp b/libs/filamat/src/Enums.cpp index 5a6a69e5ed..e9a5c76ff4 100644 --- a/libs/filamat/src/Enums.cpp +++ b/libs/filamat/src/Enums.cpp @@ -104,15 +104,15 @@ std::unordered_map& Enums::getMap() noexc return mStringToSubpassType; }; -std::unordered_map Enums::mStringToSamplerPrecision = { - { "default", SamplerPrecision::DEFAULT }, - { "low", SamplerPrecision::LOW }, - { "medium", SamplerPrecision::MEDIUM }, - { "high", SamplerPrecision::HIGH }, +std::unordered_map Enums::mStringToSamplerPrecision = { + { "default", ParameterPrecision::DEFAULT }, + { "low", ParameterPrecision::LOW }, + { "medium", ParameterPrecision::MEDIUM }, + { "high", ParameterPrecision::HIGH }, }; template <> -std::unordered_map& Enums::getMap() noexcept { +std::unordered_map& Enums::getMap() noexcept { return mStringToSamplerPrecision; }; diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 6ff2c2c322..5345c164ef 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -180,27 +180,29 @@ MaterialBuilder& MaterialBuilder::variable(Variable v, const char* name) noexcep return *this; } -MaterialBuilder& MaterialBuilder::parameter(UniformType type, const char* name) noexcept { +MaterialBuilder& MaterialBuilder::parameter( + UniformType type, const char* name, ParameterPrecision precision) noexcept { ASSERT_POSTCONDITION(mParameterCount < MAX_PARAMETERS_COUNT, "Too many parameters"); - mParameters[mParameterCount++] = { name, type, 1 }; - return *this; -} - -MaterialBuilder& MaterialBuilder::parameter(UniformType type, size_t size, const char* name) noexcept { - ASSERT_POSTCONDITION(mParameterCount < MAX_PARAMETERS_COUNT, "Too many parameters"); - mParameters[mParameterCount++] = { name, type, size }; + mParameters[mParameterCount++] = { name, type, 1, precision }; return *this; } MaterialBuilder& MaterialBuilder::parameter( - SamplerType samplerType, SamplerFormat format, SamplerPrecision precision, const char* name) noexcept { + UniformType type, size_t size, const char* name, ParameterPrecision precision) noexcept { + ASSERT_POSTCONDITION(mParameterCount < MAX_PARAMETERS_COUNT, "Too many parameters"); + mParameters[mParameterCount++] = { name, type, size, precision }; + return *this; +} + +MaterialBuilder& MaterialBuilder::parameter( + SamplerType samplerType, SamplerFormat format, ParameterPrecision precision, const char* name) noexcept { ASSERT_POSTCONDITION(mParameterCount < MAX_PARAMETERS_COUNT, "Too many parameters"); mParameters[mParameterCount++] = { name, samplerType, format, precision }; return *this; } MaterialBuilder& MaterialBuilder::parameter(SubpassType subpassType, SamplerFormat format, - SamplerPrecision precision, const char* name) noexcept { + ParameterPrecision precision, const char* name) noexcept { ASSERT_PRECONDITION(format == SamplerFormat::FLOAT, "Subpass parameters must have FLOAT format."); @@ -215,31 +217,31 @@ MaterialBuilder& MaterialBuilder::parameter(SubpassType subpassType, SamplerForm MaterialBuilder& MaterialBuilder::parameter( SamplerType samplerType, SamplerFormat format, const char* name) noexcept { - return parameter(samplerType, format, SamplerPrecision::DEFAULT, name); + return parameter(samplerType, format, ParameterPrecision::DEFAULT, name); } MaterialBuilder& MaterialBuilder::parameter( - SamplerType samplerType, SamplerPrecision precision, const char* name) noexcept { + SamplerType samplerType, ParameterPrecision precision, const char* name) noexcept { return parameter(samplerType, SamplerFormat::FLOAT, precision, name); } MaterialBuilder& MaterialBuilder::parameter( SamplerType samplerType, const char* name) noexcept { - return parameter(samplerType, SamplerFormat::FLOAT, SamplerPrecision::DEFAULT, name); + return parameter(samplerType, SamplerFormat::FLOAT, ParameterPrecision::DEFAULT, name); } MaterialBuilder& MaterialBuilder::parameter(SubpassType subpassType, SamplerFormat format, const char* name) noexcept { - return parameter(subpassType, format, SamplerPrecision::DEFAULT, name); + return parameter(subpassType, format, ParameterPrecision::DEFAULT, name); } -MaterialBuilder& MaterialBuilder::parameter(SubpassType subpassType, SamplerPrecision precision, +MaterialBuilder& MaterialBuilder::parameter(SubpassType subpassType, ParameterPrecision precision, const char* name) noexcept { return parameter(subpassType, SamplerFormat::FLOAT, precision, name); } MaterialBuilder& MaterialBuilder::parameter(SubpassType subpassType, const char* name) noexcept { - return parameter(subpassType, SamplerFormat::FLOAT, SamplerPrecision::DEFAULT, name); + return parameter(subpassType, SamplerFormat::FLOAT, ParameterPrecision::DEFAULT, name); } MaterialBuilder& MaterialBuilder::require(filament::VertexAttribute attribute) noexcept { @@ -427,7 +429,7 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept { if (param.isSampler()) { sbb.add(param.name, param.samplerType, param.format, param.precision); } else if (param.isUniform()) { - ibb.add(param.name, param.size, param.uniformType); + ibb.add(param.name, param.size, param.uniformType, param.precision); } else if (param.isSubpass()) { // For now, we only support a single subpass for attachment 0. // Subpasses blong to the "MaterialParams" block. diff --git a/tools/matc/src/matc/ParametersProcessor.cpp b/tools/matc/src/matc/ParametersProcessor.cpp index 8dbab1f9cb..e1e5116c96 100644 --- a/tools/matc/src/matc/ParametersProcessor.cpp +++ b/tools/matc/src/matc/ParametersProcessor.cpp @@ -149,8 +149,8 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json } auto precisionString = precisionValue->toJsonString(); - if (!Enums::isValid(precisionString->getString())){ - return logEnumIssue("parameters", *precisionString, Enums::map()); + if (!Enums::isValid(precisionString->getString())){ + return logEnumIssue("parameters", *precisionString, Enums::map()); } } @@ -174,10 +174,15 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json if (Enums::isValid(typeString)) { MaterialBuilder::UniformType type = Enums::toEnum(typeString); + ParameterPrecision precision = ParameterPrecision::DEFAULT; + if (precisionValue) { + precision = + Enums::toEnum(precisionValue->toJsonString()->getString()); + } if (arraySize == 0) { - builder.parameter(type, nameString.c_str()); + builder.parameter(type, nameString.c_str(), precision); } else { - builder.parameter(type, arraySize, nameString.c_str()); + builder.parameter(type, arraySize, nameString.c_str(), precision); } } else if (Enums::isValid(typeString)) { if (arraySize > 0) { @@ -191,14 +196,14 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json if (precisionValue && formatValue) { auto format = Enums::toEnum(formatValue->toJsonString()->getString()); auto precision = - Enums::toEnum(precisionValue->toJsonString()->getString()); + Enums::toEnum(precisionValue->toJsonString()->getString()); builder.parameter(type, format, precision, nameString.c_str()); } else if (formatValue) { auto format = Enums::toEnum(formatValue->toJsonString()->getString()); builder.parameter(type, format, nameString.c_str()); } else if (precisionValue) { auto precision = - Enums::toEnum(precisionValue->toJsonString()->getString()); + Enums::toEnum(precisionValue->toJsonString()->getString()); builder.parameter(type, precision, nameString.c_str()); } else { builder.parameter(type, nameString.c_str()); @@ -215,14 +220,14 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json if (precisionValue && formatValue) { auto format = Enums::toEnum(formatValue->toJsonString()->getString()); auto precision = - Enums::toEnum(precisionValue->toJsonString()->getString()); + Enums::toEnum(precisionValue->toJsonString()->getString()); builder.parameter(type, format, precision, nameString.c_str()); } else if (formatValue) { auto format = Enums::toEnum(formatValue->toJsonString()->getString()); builder.parameter(type, format, nameString.c_str()); } else if (precisionValue) { auto precision = - Enums::toEnum(precisionValue->toJsonString()->getString()); + Enums::toEnum(precisionValue->toJsonString()->getString()); builder.parameter(type, precision, nameString.c_str()); } else { builder.parameter(type, nameString.c_str());