* minimal backend support for compute - added api to dispatch a compute shader - added api to create and bind a ssbo - added api to read back a buffer Only implemented in the gl backend * Add a backend compute test suite * basic support for compute shaders in matc this is still very much work-in-progress. We're not supporting images nor ssbo for now. * rename UniformInterfaceBlock to BufferInterfaceBlock * augment BufferInterfaceBlock to support ssbo features - add support for std430 - add support for ssbo - add support for variable-size array - add support for memory qualifiers * reformat MaterialBuilder * material format: move subpasses outside of parameters subpasses now are their own json property instead of being a "parameter". * refactor parameter() methods to match Buffer/SamplerInterfaceBlock We're just shuffling the arguments. * add support for buffers in .mat files * filamat now generates buffer blocks (ssbo) * take feature level into consideration when optimizing shaders * don't store the 'uniform binding' chunk for level 2 materials this includes some refactoring/cleanups of MaterialParser * matinfo: fixes for compute - separate subpasses from parameters - don't attempt to print material properties
290 lines
8.4 KiB
C++
290 lines
8.4 KiB
C++
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "MockConfig.h"
|
|
#include "TestMaterialCompiler.h"
|
|
|
|
#include <matc/MaterialCompiler.h>
|
|
#include <matc/MaterialLexer.h>
|
|
#include <matc/JsonishLexer.h>
|
|
#include <matc/JsonishParser.h>
|
|
|
|
class MaterialLexer: public ::testing::Test {
|
|
protected:
|
|
MaterialLexer() = default;
|
|
~MaterialLexer() override = default;
|
|
};
|
|
|
|
static std::string materialSource(R"(
|
|
material {
|
|
name : "Filament Default Material",
|
|
shadingModel : unlit
|
|
}
|
|
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
material.baseColor.rgb = vec3(0.8);
|
|
}
|
|
}
|
|
)");
|
|
|
|
static std::string materialSourceWithTool(R"(
|
|
material {
|
|
name : "Filament Default Material",
|
|
shadingModel : unlit
|
|
}
|
|
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
material.baseColor.rgb = vec3(0.8);
|
|
}
|
|
}
|
|
|
|
tool {
|
|
all of this should be ignored
|
|
matching braces are fine
|
|
{ } { { } } { }
|
|
}
|
|
)");
|
|
|
|
static std::string materialSourceWithCommentedBraces(R"(
|
|
material {
|
|
name : "Filament Default Material",
|
|
shadingModel : unlit
|
|
}
|
|
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
// if (test) {
|
|
material.baseColor.rgb = vec3(0.8); // if (test) {
|
|
}
|
|
}
|
|
)");
|
|
|
|
TEST_F(MaterialLexer, NormalMaterialLexing) {
|
|
matc::MaterialLexer materialLexer;
|
|
materialLexer.lex(materialSource.c_str(), materialSource.size(), 1);
|
|
auto lexemes = materialLexer.getLexemes();
|
|
// A material grammar is made of identifiers and blocks. The source provided has one identifier,
|
|
// followed by block,identifier, and block. Total expected is four.
|
|
EXPECT_EQ(lexemes.size(), 4);
|
|
}
|
|
|
|
TEST_F(MaterialLexer, MaterialCompiler) {
|
|
matc::MaterialCompiler rawCompiler;
|
|
TestMaterialCompiler compiler(rawCompiler);
|
|
filamat::MaterialBuilder unused;
|
|
bool result = compiler.parseMaterial(materialSource.c_str(), materialSource.size(), unused);
|
|
EXPECT_EQ(result, true);
|
|
}
|
|
|
|
TEST_F(MaterialLexer, MaterialCompilerWithToolSection) {
|
|
matc::MaterialCompiler rawCompiler;
|
|
TestMaterialCompiler compiler(rawCompiler);
|
|
filamat::MaterialBuilder unused;
|
|
bool result = compiler.parseMaterial(materialSourceWithTool.c_str(), materialSourceWithTool.size(), unused);
|
|
EXPECT_EQ(result, true);
|
|
}
|
|
|
|
TEST_F(MaterialLexer, MaterialCompilerWithCommentedBraces) {
|
|
matc::MaterialCompiler rawCompiler;
|
|
TestMaterialCompiler compiler(rawCompiler);
|
|
filamat::MaterialBuilder unused;
|
|
bool result = compiler.parseMaterial(materialSourceWithCommentedBraces.c_str(), materialSourceWithCommentedBraces.size(), unused);
|
|
EXPECT_EQ(result, true);
|
|
}
|
|
|
|
TEST_F(MaterialLexer, MaterialParserErrorOnlyIdentifier) {
|
|
std::string sourceMissingIdentifier(R"(
|
|
singleIdentifier
|
|
)");
|
|
matc::MaterialCompiler rawCompiler;
|
|
TestMaterialCompiler compiler(rawCompiler);
|
|
filamat::MaterialBuilder unused;
|
|
bool result = compiler.parseMaterial(
|
|
sourceMissingIdentifier.c_str(), sourceMissingIdentifier.size(), unused);
|
|
EXPECT_EQ(result, false);
|
|
}
|
|
|
|
TEST_F(MaterialLexer, MaterialParserErrorMissingBlock) {
|
|
std::string sourceMissingBlock(R"(
|
|
identifier1 {}
|
|
identifier1
|
|
)");
|
|
matc::MaterialCompiler rawCompiler;
|
|
TestMaterialCompiler compiler(rawCompiler);
|
|
filamat::MaterialBuilder unused;
|
|
bool result = compiler.parseMaterial(
|
|
sourceMissingBlock.c_str(), sourceMissingBlock.size(), unused);
|
|
EXPECT_EQ(result, false);
|
|
}
|
|
|
|
TEST_F(MaterialLexer, MaterialParserErrorTwoBlock) {
|
|
std::string sourceTwoBlock(R"(
|
|
identifier1 {} {}
|
|
)");
|
|
matc::MaterialCompiler rawCompiler;
|
|
TestMaterialCompiler compiler(rawCompiler);
|
|
filamat::MaterialBuilder unused;
|
|
bool result = compiler.parseMaterial(sourceTwoBlock.c_str(), sourceTwoBlock.size(), unused);
|
|
EXPECT_EQ(result, false);
|
|
}
|
|
|
|
TEST_F(MaterialLexer, MaterialParserSyntaxError) {
|
|
std::string sourceSyntaxError(R"(
|
|
identifier1 {} # identified2 {}
|
|
)");
|
|
matc::MaterialCompiler rawCompiler;
|
|
TestMaterialCompiler compiler(rawCompiler);
|
|
filamat::MaterialBuilder unused;
|
|
bool result = compiler.parseMaterial(sourceSyntaxError.c_str(), sourceSyntaxError.size(), unused);
|
|
EXPECT_EQ(result, false);
|
|
}
|
|
|
|
static std::string jsonMaterialSource(R"(
|
|
{
|
|
"fragment": "void material(inout MaterialInputs material) {
|
|
vec3 normal = vec3(0.0, 0.0, 1.0);
|
|
material.normal = normal;
|
|
prepareMaterial(material);
|
|
material.baseColor = vec4(1.0, 1.0, 1.0, 1.0) * materialParams.baseColorFactor;
|
|
material.metallic = materialParams.metallicFactor;
|
|
material.roughness = materialParams.roughnessFactor;
|
|
material.ambientOcclusion = 1.0;
|
|
material.emissive = vec4(0.0);
|
|
material.reflectance = 0.5;
|
|
// material.baseColor.xyz = normal;\n}",
|
|
"material": {
|
|
"blending": "opaque",
|
|
"name": "Gltf 2 Metallic-Roughness Material",
|
|
"parameters": [
|
|
{
|
|
"name": "baseColorFactor",
|
|
"type": "float4"
|
|
},
|
|
{
|
|
"name": "metallicFactor",
|
|
"type": "float"
|
|
},
|
|
{
|
|
"name": "roughnessFactor",
|
|
"type": "float"
|
|
},
|
|
{
|
|
"name": "emissiveFactor",
|
|
"type": "float4"
|
|
},
|
|
{
|
|
"name": "weights2d",
|
|
"type": "float[9]"
|
|
}
|
|
],
|
|
"requires": [
|
|
"position",
|
|
"tangents",
|
|
"uv0"
|
|
],
|
|
"shadingModel": "lit"
|
|
}
|
|
}
|
|
)");
|
|
|
|
static std::string jsonMaterialSourceNoQuotes(R"({
|
|
|
|
material: {
|
|
blending: opaque,
|
|
name: albertCamus,
|
|
parameters: [
|
|
{
|
|
name: baseColorFactor,
|
|
type: float4
|
|
},
|
|
{
|
|
name: metallicFactor,
|
|
type: float
|
|
},
|
|
{
|
|
name: roughnessFactor,
|
|
type: float
|
|
},
|
|
{
|
|
name: emissiveFactor,
|
|
type: float4
|
|
},
|
|
{
|
|
name: weights2d,
|
|
type: float[9]
|
|
}
|
|
],
|
|
requires: [
|
|
position,
|
|
tangents,
|
|
uv0
|
|
],
|
|
shadingModel: lit
|
|
}
|
|
|
|
})");
|
|
|
|
TEST_F(MaterialLexer, JsonMaterialLexingAndParsing) {
|
|
matc::JsonishLexer jsonishLexer;
|
|
jsonishLexer.lex(jsonMaterialSource.c_str(), jsonMaterialSource.size(), 1);
|
|
auto lexemes = jsonishLexer.getLexemes();
|
|
|
|
EXPECT_TRUE(!lexemes.empty());
|
|
|
|
matc::JsonishParser jsonishParser(lexemes);
|
|
std::unique_ptr<matc::JsonishObject> root = jsonishParser.parse();
|
|
|
|
auto entries = root->getEntries();
|
|
EXPECT_TRUE(entries.size() == 2);
|
|
EXPECT_TRUE(entries.find("fragment") != entries.end());
|
|
EXPECT_TRUE(entries.find("material") != entries.end());
|
|
}
|
|
|
|
TEST_F(MaterialLexer, JsonMaterialLexingAndParsingNoQuotes) {
|
|
matc::JsonishLexer jsonishLexer;
|
|
jsonishLexer.lex(jsonMaterialSourceNoQuotes.c_str(), jsonMaterialSourceNoQuotes.size(), 1);
|
|
auto lexemes = jsonishLexer.getLexemes();
|
|
|
|
EXPECT_TRUE(!lexemes.empty());
|
|
|
|
matc::JsonishParser jsonishParser(lexemes);
|
|
std::unique_ptr<matc::JsonishObject> root = jsonishParser.parse();
|
|
|
|
auto entries = root->getEntries();
|
|
EXPECT_TRUE(entries.size() == 1);
|
|
EXPECT_TRUE(entries.find("material") != entries.end());
|
|
}
|
|
|
|
TEST_F(MaterialLexer, JsonMaterialCompiler) {
|
|
matc::MaterialCompiler rawCompiler;
|
|
TestMaterialCompiler compiler(rawCompiler);
|
|
filamat::MaterialBuilder unused;
|
|
bool result = compiler.parseMaterialAsJSON(jsonMaterialSource.c_str(), jsonMaterialSource.size(), unused);
|
|
EXPECT_EQ(result, true);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|