Support backends with multiple shader languages and precompiled Metal libraries (#7769)
This commit is contained in:
committed by
Benjamin Doherty
parent
d9cba80bcf
commit
35fa79ec23
@@ -84,6 +84,9 @@ public:
|
||||
// null terminating character.
|
||||
Program& shader(ShaderStage shader, void const* data, size_t size);
|
||||
|
||||
// sets the language of the shader sources provided with shader() (defaults to ESSL3)
|
||||
Program& shaderLanguage(ShaderLanguage shaderLanguage);
|
||||
|
||||
// Note: This is only needed for GLES3.0 backends, because the layout(binding=) syntax is
|
||||
// not permitted in glsl. The backend needs a way to associate a uniform block
|
||||
// to a binding point.
|
||||
@@ -136,6 +139,8 @@ public:
|
||||
utils::CString const& getName() const noexcept { return mName; }
|
||||
utils::CString& getName() noexcept { return mName; }
|
||||
|
||||
auto const& getShaderLanguage() const { return mShaderLanguage; }
|
||||
|
||||
utils::FixedCapacityVector<SpecializationConstant> const& getSpecializationConstants() const noexcept {
|
||||
return mSpecializationConstants;
|
||||
}
|
||||
@@ -155,6 +160,7 @@ private:
|
||||
UniformBlockInfo mUniformBlocks = {};
|
||||
SamplerGroupInfo mSamplerGroups = {};
|
||||
ShaderSource mShadersSource;
|
||||
ShaderLanguage mShaderLanguage = ShaderLanguage::ESSL3;
|
||||
utils::CString mName;
|
||||
uint64_t mCacheId{};
|
||||
utils::Invocable<utils::io::ostream&(utils::io::ostream& out)> mLogger;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace filament::backend {
|
||||
using namespace utils;
|
||||
|
||||
// We want these in the .cpp file, so they're not inlined (not worth it)
|
||||
Program::Program() noexcept { // NOLINT(modernize-use-equals-default)
|
||||
Program::Program() noexcept { // NOLINT(modernize-use-equals-default)
|
||||
}
|
||||
|
||||
Program::Program(Program&& rhs) noexcept = default;
|
||||
@@ -47,6 +47,11 @@ Program& Program::shader(ShaderStage shader, void const* data, size_t size) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::shaderLanguage(ShaderLanguage shaderLanguage) {
|
||||
mShaderLanguage = shaderLanguage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::uniformBlockBindings(
|
||||
FixedCapacityVector<std::pair<utils::CString, uint8_t>> const& uniformBlockBindings) noexcept {
|
||||
for (auto const& item : uniformBlockBindings) {
|
||||
|
||||
@@ -106,26 +106,41 @@ bool MetalShaderCompiler::isParallelShaderCompileSupported() const noexcept {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert_invariant(source[source.size() - 1] == '\0');
|
||||
|
||||
// the shader string is null terminated and the length includes the null character
|
||||
NSString* objcSource = [[NSString alloc] initWithBytes:source.data()
|
||||
length:source.size() - 1
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
// By default, Metal uses the most recent language version.
|
||||
MTLCompileOptions* options = [MTLCompileOptions new];
|
||||
|
||||
// Disable Fast Math optimizations.
|
||||
// This ensures that operations adhere to IEEE standards for floating-point arithmetic,
|
||||
// which is crucial for half precision floats in scenarios where fast math optimizations
|
||||
// lead to inaccuracies, such as in handling special values like NaN or Infinity.
|
||||
options.fastMathEnabled = NO;
|
||||
|
||||
NSError* error = nil;
|
||||
id<MTLLibrary> library = [device newLibraryWithSource:objcSource
|
||||
options:options
|
||||
error:&error];
|
||||
id<MTLLibrary> library = nil;
|
||||
switch (program.getShaderLanguage()) {
|
||||
case ShaderLanguage::MSL: {
|
||||
// By default, Metal uses the most recent language version.
|
||||
MTLCompileOptions* options = [MTLCompileOptions new];
|
||||
|
||||
// Disable Fast Math optimizations.
|
||||
// This ensures that operations adhere to IEEE standards for floating-point
|
||||
// arithmetic, which is crucial for half precision floats in scenarios where fast
|
||||
// math optimizations lead to inaccuracies, such as in handling special values like
|
||||
// NaN or Infinity.
|
||||
options.fastMathEnabled = NO;
|
||||
|
||||
assert_invariant(source[source.size() - 1] == '\0');
|
||||
// the shader string is null terminated and the length includes the null character
|
||||
NSString* objcSource = [[NSString alloc] initWithBytes:source.data()
|
||||
length:source.size() - 1
|
||||
encoding:NSUTF8StringEncoding];
|
||||
library = [device newLibraryWithSource:objcSource options:options error:&error];
|
||||
break;
|
||||
}
|
||||
case ShaderLanguage::METAL_LIBRARY: {
|
||||
dispatch_data_t data = dispatch_data_create(source.data(), source.size(),
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||
DISPATCH_DATA_DESTRUCTOR_DEFAULT);
|
||||
library = [device newLibraryWithData:data error:&error];
|
||||
break;
|
||||
}
|
||||
case ShaderLanguage::ESSL1:
|
||||
case ShaderLanguage::ESSL3:
|
||||
case ShaderLanguage::SPIRV:
|
||||
break;
|
||||
}
|
||||
|
||||
if (library == nil) {
|
||||
NSString* errorMessage = @"unknown error";
|
||||
if (error) {
|
||||
|
||||
@@ -79,6 +79,20 @@ ShaderGenerator::ShaderGenerator(std::string vertex, std::string fragment,
|
||||
mVertexBlob(transpileShader(ShaderStage::VERTEX, std::move(vertex), backend, isMobile, sib)),
|
||||
mFragmentBlob(transpileShader(ShaderStage::FRAGMENT, std::move(fragment), backend,
|
||||
isMobile, sib)) {
|
||||
switch (backend) {
|
||||
case Backend::OPENGL:
|
||||
mShaderLanguage = filament::backend::ShaderLanguage::ESSL3;
|
||||
break;
|
||||
case Backend::VULKAN:
|
||||
mShaderLanguage = filament::backend::ShaderLanguage::SPIRV;
|
||||
break;
|
||||
case Backend::METAL:
|
||||
mShaderLanguage = filament::backend::ShaderLanguage::MSL;
|
||||
break;
|
||||
case Backend::NOOP:
|
||||
mShaderLanguage = filament::backend::ShaderLanguage::ESSL3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ShaderGenerator::Blob ShaderGenerator::transpileShader(
|
||||
@@ -160,6 +174,7 @@ ShaderGenerator::Blob ShaderGenerator::transpileShader(
|
||||
|
||||
Program ShaderGenerator::getProgram(filament::backend::DriverApi&) noexcept {
|
||||
Program program;
|
||||
program.shaderLanguage(mShaderLanguage);
|
||||
program.shader(ShaderStage::VERTEX, mVertexBlob.data(), mVertexBlob.size());
|
||||
program.shader(ShaderStage::FRAGMENT, mFragmentBlob.data(), mFragmentBlob.size());
|
||||
return program;
|
||||
|
||||
@@ -60,6 +60,7 @@ private:
|
||||
Blob mFragmentBlob;
|
||||
std::string mCompiledVertexShader;
|
||||
std::string mCompiledFragmentShader;
|
||||
filament::backend::ShaderLanguage mShaderLanguage;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ kernel void main0() {}
|
||||
}
|
||||
|
||||
Program program;
|
||||
program.shaderLanguage(ShaderLanguage::ESSL3);
|
||||
program.shader(ShaderStage::COMPUTE, shader.data(), shader.size() + 1);
|
||||
|
||||
Handle<HwProgram> ph = driver.createProgram(std::move(program));
|
||||
@@ -144,6 +145,7 @@ kernel void main0(device Output_data& output_data [[buffer(0)]],
|
||||
driver.updateBufferObject(input_data, { data.data(), size }, 0);
|
||||
|
||||
Program program;
|
||||
program.shaderLanguage(ShaderLanguage::ESSL3);
|
||||
program.shader(ShaderStage::COMPUTE, shader.data(), shader.size() + 1);
|
||||
Handle<HwProgram> ph = driver.createProgram(std::move(program));
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <utils/CString.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <optional>
|
||||
|
||||
using namespace utils;
|
||||
using namespace filament::backend;
|
||||
@@ -42,36 +43,31 @@ using namespace filamat;
|
||||
|
||||
namespace filament {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
MaterialParser::MaterialParserDetails::MaterialParserDetails(ShaderLanguage language, const void* data, size_t size)
|
||||
: mManagedBuffer(data, size),
|
||||
mChunkContainer(mManagedBuffer.data(), mManagedBuffer.size()),
|
||||
mMaterialChunk(mChunkContainer) {
|
||||
constexpr std::pair<ChunkType, ChunkType> shaderLanguageToTags(ShaderLanguage language) {
|
||||
switch (language) {
|
||||
case ShaderLanguage::ESSL3:
|
||||
mMaterialTag = ChunkType::MaterialGlsl;
|
||||
mDictionaryTag = ChunkType::DictionaryText;
|
||||
break;
|
||||
return { ChunkType::MaterialGlsl, ChunkType::DictionaryText };
|
||||
case ShaderLanguage::ESSL1:
|
||||
mMaterialTag = ChunkType::MaterialEssl1;
|
||||
mDictionaryTag = ChunkType::DictionaryText;
|
||||
break;
|
||||
return { ChunkType::MaterialEssl1, ChunkType::DictionaryText };
|
||||
case ShaderLanguage::MSL:
|
||||
mMaterialTag = ChunkType::MaterialMetal;
|
||||
mDictionaryTag = ChunkType::DictionaryText;
|
||||
break;
|
||||
return { ChunkType::MaterialMetal, ChunkType::DictionaryText };
|
||||
case ShaderLanguage::SPIRV:
|
||||
mMaterialTag = ChunkType::MaterialSpirv;
|
||||
mDictionaryTag = ChunkType::DictionarySpirv;
|
||||
break;
|
||||
return { ChunkType::MaterialSpirv, ChunkType::DictionarySpirv };
|
||||
case ShaderLanguage::METAL_LIBRARY:
|
||||
mMaterialTag = ChunkType::MaterialMetalLibrary;
|
||||
mDictionaryTag = ChunkType::DictionaryMetalLibrary;
|
||||
break;
|
||||
return { ChunkType::MaterialMetalLibrary, ChunkType::DictionaryMetalLibrary };
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
MaterialParser::MaterialParserDetails::MaterialParserDetails(
|
||||
const utils::FixedCapacityVector<ShaderLanguage>& preferredLanguages, const void* data,
|
||||
size_t size)
|
||||
: mManagedBuffer(data, size),
|
||||
mChunkContainer(mManagedBuffer.data(), mManagedBuffer.size()),
|
||||
mPreferredLanguages(preferredLanguages),
|
||||
mMaterialChunk(mChunkContainer) {}
|
||||
|
||||
template<typename T>
|
||||
UTILS_NOINLINE
|
||||
bool MaterialParser::MaterialParserDetails::getFromSimpleChunk(
|
||||
@@ -87,9 +83,9 @@ bool MaterialParser::MaterialParserDetails::getFromSimpleChunk(
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
MaterialParser::MaterialParser(ShaderLanguage language, const void* data, size_t size)
|
||||
: mImpl(language, data, size) {
|
||||
}
|
||||
MaterialParser::MaterialParser(utils::FixedCapacityVector<ShaderLanguage> preferredLanguages,
|
||||
const void* data, size_t size)
|
||||
: mImpl(preferredLanguages, data, size) {}
|
||||
|
||||
ChunkContainer& MaterialParser::getChunkContainer() noexcept {
|
||||
return mImpl.mChunkContainer;
|
||||
@@ -104,20 +100,40 @@ MaterialParser::ParseResult MaterialParser::parse() noexcept {
|
||||
if (UTILS_UNLIKELY(!cc.parse())) {
|
||||
return ParseResult::ERROR_OTHER;
|
||||
}
|
||||
const ChunkType matTag = mImpl.mMaterialTag;
|
||||
const ChunkType dictTag = mImpl.mDictionaryTag;
|
||||
if (UTILS_UNLIKELY(!cc.hasChunk(matTag) || !cc.hasChunk(dictTag))) {
|
||||
|
||||
using MaybeShaderLanguageAndChunks =
|
||||
std::optional<std::tuple<ShaderLanguage, ChunkType, ChunkType>>;
|
||||
auto chooseLanguage = [this, &cc]() -> MaybeShaderLanguageAndChunks {
|
||||
for (auto language : mImpl.mPreferredLanguages) {
|
||||
const auto [matTag, dictTag] = shaderLanguageToTags(language);
|
||||
if (cc.hasChunk(matTag) && cc.hasChunk(dictTag)) {
|
||||
return std::make_tuple(language, matTag, dictTag);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
};
|
||||
const auto result = chooseLanguage();
|
||||
|
||||
if (!result.has_value()) {
|
||||
return ParseResult::ERROR_MISSING_BACKEND;
|
||||
}
|
||||
|
||||
const auto [chosenLanguage, matTag, dictTag] = result.value();
|
||||
if (UTILS_UNLIKELY(!DictionaryReader::unflatten(cc, dictTag, mImpl.mBlobDictionary))) {
|
||||
return ParseResult::ERROR_OTHER;
|
||||
}
|
||||
if (UTILS_UNLIKELY(!mImpl.mMaterialChunk.initialize(matTag))) {
|
||||
return ParseResult::ERROR_OTHER;
|
||||
}
|
||||
|
||||
mImpl.mChosenLanguage = chosenLanguage;
|
||||
return ParseResult::SUCCESS;
|
||||
}
|
||||
|
||||
backend::ShaderLanguage MaterialParser::getShaderLanguage() const noexcept {
|
||||
return mImpl.mChosenLanguage;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
bool MaterialParser::getMaterialVersion(uint32_t* value) const noexcept {
|
||||
return mImpl.getFromSimpleChunk(ChunkType::MaterialVersion, value);
|
||||
|
||||
@@ -29,10 +29,12 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Program.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <utility>
|
||||
|
||||
namespace filaflat {
|
||||
class ChunkContainer;
|
||||
@@ -48,7 +50,8 @@ struct MaterialConstant;
|
||||
|
||||
class MaterialParser {
|
||||
public:
|
||||
MaterialParser(backend::ShaderLanguage language, const void* data, size_t size);
|
||||
MaterialParser(utils::FixedCapacityVector<backend::ShaderLanguage> preferredLanguages,
|
||||
const void* data, size_t size);
|
||||
|
||||
MaterialParser(MaterialParser const& rhs) noexcept = delete;
|
||||
MaterialParser& operator=(MaterialParser const& rhs) noexcept = delete;
|
||||
@@ -60,6 +63,7 @@ public:
|
||||
};
|
||||
|
||||
ParseResult parse() noexcept;
|
||||
backend::ShaderLanguage getShaderLanguage() const noexcept;
|
||||
|
||||
// Accessors
|
||||
bool getMaterialVersion(uint32_t* value) const noexcept;
|
||||
@@ -130,7 +134,9 @@ public:
|
||||
|
||||
private:
|
||||
struct MaterialParserDetails {
|
||||
MaterialParserDetails(backend::ShaderLanguage language, const void* data, size_t size);
|
||||
MaterialParserDetails(
|
||||
const utils::FixedCapacityVector<backend::ShaderLanguage>& preferredLanguages,
|
||||
const void* data, size_t size);
|
||||
|
||||
template<typename T>
|
||||
bool getFromSimpleChunk(filamat::ChunkType type, T* value) const noexcept;
|
||||
@@ -157,12 +163,12 @@ private:
|
||||
|
||||
ManagedBuffer mManagedBuffer;
|
||||
filaflat::ChunkContainer mChunkContainer;
|
||||
utils::FixedCapacityVector<backend::ShaderLanguage> mPreferredLanguages;
|
||||
backend::ShaderLanguage mChosenLanguage;
|
||||
|
||||
// Keep MaterialChunk alive between calls to getShader to avoid reload the shader index.
|
||||
filaflat::MaterialChunk mMaterialChunk;
|
||||
filaflat::BlobDictionary mBlobDictionary;
|
||||
filamat::ChunkType mMaterialTag = filamat::ChunkType::Unknown;
|
||||
filamat::ChunkType mDictionaryTag = filamat::ChunkType::Unknown;
|
||||
};
|
||||
|
||||
filaflat::ChunkContainer& getChunkContainer() noexcept;
|
||||
|
||||
@@ -59,10 +59,11 @@
|
||||
#include <filament/Texture.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/JobSystem.h>
|
||||
#include <utils/CountDownLatch.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/JobSystem.h>
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
@@ -231,19 +232,21 @@ public:
|
||||
return mPlatform;
|
||||
}
|
||||
|
||||
backend::ShaderLanguage getShaderLanguage() const noexcept {
|
||||
// Return a vector of shader languages, in order of preference.
|
||||
utils::FixedCapacityVector<backend::ShaderLanguage> getShaderLanguage() const noexcept {
|
||||
switch (mBackend) {
|
||||
case Backend::DEFAULT:
|
||||
case Backend::NOOP:
|
||||
default:
|
||||
return backend::ShaderLanguage::ESSL3;
|
||||
return { backend::ShaderLanguage::ESSL3 };
|
||||
case Backend::OPENGL:
|
||||
return getDriver().getFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0
|
||||
? backend::ShaderLanguage::ESSL1 : backend::ShaderLanguage::ESSL3;
|
||||
return { getDriver().getFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0
|
||||
? backend::ShaderLanguage::ESSL1
|
||||
: backend::ShaderLanguage::ESSL3 };
|
||||
case Backend::VULKAN:
|
||||
return backend::ShaderLanguage::SPIRV;
|
||||
return { backend::ShaderLanguage::SPIRV };
|
||||
case Backend::METAL:
|
||||
return backend::ShaderLanguage::MSL;
|
||||
return { backend::ShaderLanguage::METAL_LIBRARY, backend::ShaderLanguage::MSL };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,16 +42,16 @@
|
||||
#include <backend/Program.h>
|
||||
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Hash.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/Hash.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -60,6 +60,7 @@
|
||||
#include <mutex>
|
||||
#include <new>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
@@ -74,22 +75,32 @@ using namespace backend;
|
||||
using namespace filaflat;
|
||||
using namespace utils;
|
||||
|
||||
static std::unique_ptr<MaterialParser> createParser(
|
||||
Backend backend, ShaderLanguage language, const void* data, size_t size) {
|
||||
static std::unique_ptr<MaterialParser> createParser(Backend backend,
|
||||
utils::FixedCapacityVector<ShaderLanguage> languages, const void* data, size_t size) {
|
||||
// unique_ptr so we don't leak MaterialParser on failures below
|
||||
auto materialParser = std::make_unique<MaterialParser>(language, data, size);
|
||||
auto materialParser = std::make_unique<MaterialParser>(languages, data, size);
|
||||
|
||||
MaterialParser::ParseResult const materialResult = materialParser->parse();
|
||||
|
||||
if (UTILS_UNLIKELY(materialResult == MaterialParser::ParseResult::ERROR_MISSING_BACKEND)) {
|
||||
std::stringstream languageNames;
|
||||
for (auto it = languages.begin(); it != languages.end(); ++it) {
|
||||
languageNames << shaderLanguageToString(*it);
|
||||
if (std::next(it) != languages.end()) {
|
||||
languageNames << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_PRECONDITION(materialResult != MaterialParser::ParseResult::ERROR_MISSING_BACKEND,
|
||||
"the material was not built for any of the %s backend's supported shader "
|
||||
"languages (%s)\n",
|
||||
backendToString(backend), languageNames.str().c_str());
|
||||
}
|
||||
|
||||
if (backend == Backend::NOOP) {
|
||||
return materialParser;
|
||||
}
|
||||
|
||||
ASSERT_PRECONDITION(materialResult != MaterialParser::ParseResult::ERROR_MISSING_BACKEND,
|
||||
"the material was not built for the %s backend and %s shader language\n",
|
||||
backendToString(backend),
|
||||
shaderLanguageToString(language));
|
||||
|
||||
ASSERT_PRECONDITION(materialResult == MaterialParser::ParseResult::SUCCESS,
|
||||
"could not parse the material package");
|
||||
|
||||
@@ -217,7 +228,7 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder,
|
||||
success = parser->getUIB(&mUniformInterfaceBlock);
|
||||
assert_invariant(success);
|
||||
|
||||
if (UTILS_UNLIKELY(engine.getShaderLanguage() == ShaderLanguage::ESSL1)) {
|
||||
if (UTILS_UNLIKELY(parser->getShaderLanguage() == ShaderLanguage::ESSL1)) {
|
||||
success = parser->getBindingUniformInfo(&mBindingUniformInfo);
|
||||
assert_invariant(success);
|
||||
|
||||
@@ -530,6 +541,7 @@ Program FMaterial::getProgramWithVariants(
|
||||
Program program;
|
||||
program.shader(ShaderStage::VERTEX, vsBuilder.data(), vsBuilder.size())
|
||||
.shader(ShaderStage::FRAGMENT, fsBuilder.data(), fsBuilder.size())
|
||||
.shaderLanguage(mMaterialParser->getShaderLanguage())
|
||||
.uniformBlockBindings(mUniformBlockBindings)
|
||||
.diagnostics(mName,
|
||||
[this, variant](io::ostream& out) -> io::ostream& {
|
||||
@@ -551,8 +563,7 @@ Program FMaterial::getProgramWithVariants(
|
||||
samplers.data(), info.count);
|
||||
}
|
||||
}
|
||||
|
||||
if (UTILS_UNLIKELY(mEngine.getShaderLanguage() == ShaderLanguage::ESSL1)) {
|
||||
if (UTILS_UNLIKELY(mMaterialParser->getShaderLanguage() == ShaderLanguage::ESSL1)) {
|
||||
assert_invariant(!mBindingUniformInfo.empty());
|
||||
for (auto const& [index, uniforms] : mBindingUniformInfo) {
|
||||
program.uniforms(uint32_t(index), uniforms);
|
||||
@@ -861,7 +872,7 @@ void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builde
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_STEREO_EYE_COUNT,
|
||||
(int)engine.getConfig().stereoscopicEyeCount });
|
||||
if (UTILS_UNLIKELY(engine.getShaderLanguage() == ShaderLanguage::ESSL1)) {
|
||||
if (UTILS_UNLIKELY(parser->getShaderLanguage() == ShaderLanguage::ESSL1)) {
|
||||
// The actual value of this spec-constant is set in the OpenGLDriver backend.
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_SRGB_SWAPCHAIN_EMULATION,
|
||||
|
||||
@@ -31,7 +31,7 @@ using namespace filament;
|
||||
// This will re-compile the test material with the current version of matc.
|
||||
// To verify, rebuild and re-run test_material_parser (this test suite).
|
||||
TEST(MaterialParser, Parse) {
|
||||
MaterialParser parser(backend::ShaderLanguage::ESSL3,
|
||||
MaterialParser parser({ backend::ShaderLanguage::ESSL3 },
|
||||
FILAMENT_TEST_RESOURCES_TEST_MATERIAL_DATA, FILAMENT_TEST_RESOURCES_TEST_MATERIAL_SIZE);
|
||||
MaterialParser::ParseResult materialOk = parser.parse();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user