308 lines
10 KiB
C++
308 lines
10 KiB
C++
/*
|
|
* Copyright (C) 2019 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 <filaflat/ChunkContainer.h>
|
|
|
|
#include <filament/MaterialEnums.h>
|
|
|
|
#include <backend/DriverEnums.h>
|
|
|
|
#include <matdbg/JsonWriter.h>
|
|
#include <matdbg/ShaderInfo.h>
|
|
|
|
#include "CommonWriter.h"
|
|
|
|
#include <private/filament/Variant.h>
|
|
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
|
|
using namespace filament;
|
|
using namespace backend;
|
|
using namespace filaflat;
|
|
using namespace filamat;
|
|
using namespace std;
|
|
using namespace utils;
|
|
|
|
namespace filament {
|
|
namespace matdbg {
|
|
|
|
static std::string arraySizeToString(uint64_t size) {
|
|
if (size > 1) {
|
|
std::string s = "[";
|
|
s += size;
|
|
s += "]";
|
|
return s;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
template<typename T, typename V>
|
|
static void printChunk(ostream& json, const ChunkContainer& container, ChunkType type,
|
|
const char* title) {
|
|
T value;
|
|
if (read(container, type, reinterpret_cast<V*>(&value))) {
|
|
json << "\"" << title << "\": \"" << toString(value) << "\",\n";
|
|
}
|
|
}
|
|
|
|
static void printFloatChunk(ostream& json, const ChunkContainer& container, ChunkType type,
|
|
const char* title) {
|
|
float value;
|
|
if (read(container, type, &value)) {
|
|
json << "\"" << title << "\": " << setprecision(2) << value << ",\n";
|
|
}
|
|
}
|
|
|
|
static void printUint32Chunk(ostream& json, const ChunkContainer& container,
|
|
ChunkType type, const char* title) {
|
|
uint32_t value;
|
|
if (read(container, type, &value)) {
|
|
json << "\"" << title << "\": " << value << ",\n";
|
|
}
|
|
}
|
|
|
|
static void printStringChunk(ostream& json, const ChunkContainer& container,
|
|
ChunkType type, const char* title) {
|
|
CString value;
|
|
if (read(container, type, &value)) {
|
|
json << "\"" << title << "\": \"" << value.c_str_safe() << "\",\n";
|
|
}
|
|
}
|
|
|
|
static bool printMaterial(ostream& json, const ChunkContainer& container) {
|
|
printStringChunk(json, container, MaterialName, "name");
|
|
printUint32Chunk(json, container, MaterialVersion, "version");
|
|
printUint32Chunk(json, container, MaterialFeatureLevel, "feature_level");
|
|
json << "\"shading\": {\n";
|
|
printChunk<Shading, uint8_t>(json, container, MaterialShading, "model");
|
|
printChunk<MaterialDomain, uint8_t>(json, container, ChunkType::MaterialDomain, "material_domain");
|
|
printChunk<UserVariantFilterMask, uint8_t>(json, container, ChunkType::MaterialVariantFilterMask, "variant_filter_mask");
|
|
printChunk<VertexDomain, uint8_t>(json, container, MaterialVertexDomain, "vertex_domain");
|
|
printChunk<Interpolation, uint8_t>(json, container, MaterialInterpolation, "interpolation");
|
|
printChunk<bool, bool>(json, container, MaterialShadowMultiplier, "shadow_multiply");
|
|
printChunk<bool, bool>(json, container, MaterialSpecularAntiAliasing, "specular_antialiasing");
|
|
printFloatChunk(json, container, MaterialSpecularAntiAliasingVariance, "variance");
|
|
printFloatChunk(json, container, MaterialSpecularAntiAliasingThreshold, "threshold");
|
|
printChunk<bool, bool>(json, container, MaterialClearCoatIorChange, "clear_coat_IOR_change");
|
|
json << "\"_\": 0 },\n";
|
|
json << "\"raster\": {\n";
|
|
printChunk<BlendingMode, uint8_t>(json, container, MaterialBlendingMode, "blending");
|
|
printFloatChunk(json, container, MaterialMaskThreshold, "mask_threshold");
|
|
printChunk<bool, bool>(json, container, MaterialColorWrite, "color_write");
|
|
printChunk<bool, bool>(json, container, MaterialDepthWrite, "depth_write");
|
|
printChunk<bool, bool>(json, container, MaterialDepthTest, "depth_test");
|
|
printChunk<bool, bool>(json, container, MaterialInstanced, "instanced");
|
|
printChunk<bool, bool>(json, container, MaterialDoubleSided, "double_sided");
|
|
printChunk<CullingMode, uint8_t>(json, container, MaterialCullingMode, "culling");
|
|
printChunk<TransparencyMode, uint8_t>(json, container, MaterialTransparencyMode, "transparency");
|
|
json << "\"_\": 0 },\n";
|
|
return true;
|
|
}
|
|
|
|
static bool printParametersInfo(ostream&, const ChunkContainer&) {
|
|
// TODO
|
|
return true;
|
|
}
|
|
|
|
static void printShaderInfo(ostream& json, const vector<ShaderInfo>& info, const ChunkContainer& container) {
|
|
MaterialDomain domain = MaterialDomain::SURFACE;
|
|
read(container, ChunkType::MaterialDomain, reinterpret_cast<uint8_t*>(&domain));
|
|
for (uint64_t i = 0; i < info.size(); ++i) {
|
|
const auto& item = info[i];
|
|
string variantString = formatVariantString(item.variant, domain);
|
|
string ps = (item.pipelineStage == backend::ShaderStage::VERTEX) ? "vertex " : "fragment";
|
|
json
|
|
<< " {"
|
|
<< "\"index\": \"" << std::setw(2) << i << "\", "
|
|
<< "\"shaderModel\": \"" << toString(item.shaderModel) << "\", "
|
|
<< "\"pipelineStage\": \"" << ps << "\", "
|
|
<< "\"variantString\": \"" << variantString << "\", "
|
|
<< "\"variant\": " << +item.variant.key << " }"
|
|
<< ((i == info.size() - 1) ? "\n" : ",\n");
|
|
}
|
|
}
|
|
|
|
static bool printGlslInfo(ostream& json, const ChunkContainer& container, ChunkType chunkType) {
|
|
std::vector<ShaderInfo> info;
|
|
info.resize(getShaderCount(container, chunkType));
|
|
if (!getShaderInfo(container, info.data(), chunkType)) {
|
|
return false;
|
|
}
|
|
switch (chunkType) {
|
|
case ChunkType::MaterialEssl1:
|
|
json << "\"essl1\": [\n";
|
|
break;
|
|
case ChunkType::MaterialGlsl:
|
|
json << "\"opengl\": [\n";
|
|
break;
|
|
default:
|
|
assert(false); // unreachable
|
|
}
|
|
printShaderInfo(json, info, container);
|
|
json << "],\n";
|
|
return true;
|
|
}
|
|
|
|
static bool printVkInfo(ostream& json, const ChunkContainer& container) {
|
|
std::vector<ShaderInfo> info;
|
|
info.resize(getShaderCount(container, ChunkType::MaterialSpirv));
|
|
if (!getShaderInfo(container, info.data(), ChunkType::MaterialSpirv)) {
|
|
return false;
|
|
}
|
|
json << "\"vulkan\": [\n";
|
|
printShaderInfo(json, info, container);
|
|
json << "],\n";
|
|
return true;
|
|
}
|
|
|
|
static bool printMetalInfo(ostream& json, const ChunkContainer& container) {
|
|
std::vector<ShaderInfo> info;
|
|
info.resize(getShaderCount(container, ChunkType::MaterialMetal));
|
|
if (!getShaderInfo(container, info.data(), ChunkType::MaterialMetal)) {
|
|
return false;
|
|
}
|
|
json << "\"metal\": [\n";
|
|
printShaderInfo(json, info, container);
|
|
json << "],\n";
|
|
return true;
|
|
}
|
|
|
|
static bool printWGPUInfo(ostream& json, const ChunkContainer& container) {
|
|
std::vector<ShaderInfo> info;
|
|
info.resize(getShaderCount(container, ChunkType::MaterialWgsl));
|
|
if (!getShaderInfo(container, info.data(), ChunkType::MaterialWgsl)) {
|
|
return false;
|
|
}
|
|
json << "\"webgpu\": [\n";
|
|
printShaderInfo(json, info, container);
|
|
json << "],\n";
|
|
return true;
|
|
}
|
|
|
|
bool JsonWriter::writeMaterialInfo(const filaflat::ChunkContainer& container) {
|
|
ostringstream json;
|
|
if (!printMaterial(json, container)) {
|
|
return false;
|
|
}
|
|
if (!printParametersInfo(json, container)) {
|
|
return false;
|
|
}
|
|
if (!printGlslInfo(json, container, ChunkType::MaterialGlsl)) {
|
|
return false;
|
|
}
|
|
if (!printGlslInfo(json, container, ChunkType::MaterialEssl1)) {
|
|
return false;
|
|
}
|
|
if (!printVkInfo(json, container)) {
|
|
return false;
|
|
}
|
|
if (!printMetalInfo(json, container)) {
|
|
return false;
|
|
}
|
|
if (!printWGPUInfo(json, container)) {
|
|
return false;
|
|
}
|
|
|
|
json << "\"required_attributes\": [\n";
|
|
uint32_t requiredAttributes;
|
|
if (read(container, MaterialRequiredAttributes, &requiredAttributes)) {
|
|
string comma;
|
|
AttributeBitset bitset;
|
|
bitset.setValue(requiredAttributes);
|
|
if (bitset.count() > 0) {
|
|
for (size_t i = 0; i < bitset.size(); i++) {
|
|
if (bitset.test(i)) {
|
|
json << comma << "\"" << toString(static_cast<VertexAttribute>(i)) << "\"";
|
|
comma = ",";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
json << "]\n";
|
|
|
|
mJsonString = CString(json.str().c_str());
|
|
return true;
|
|
}
|
|
|
|
const char* JsonWriter::getJsonString() const {
|
|
return mJsonString.c_str();
|
|
}
|
|
|
|
size_t JsonWriter::getJsonSize() const {
|
|
return mJsonString.size();
|
|
}
|
|
|
|
bool JsonWriter::writeActiveInfo(const filaflat::ChunkContainer& package,
|
|
ShaderLanguage shaderLanguage, DbgShaderModel shaderModel, VariantList activeVariants) {
|
|
vector<ShaderInfo> shaders;
|
|
ostringstream json;
|
|
json << "[\"";
|
|
ChunkType chunkType;
|
|
switch (shaderLanguage) {
|
|
case ShaderLanguage::ESSL1:
|
|
json << "essl1";
|
|
chunkType = ChunkType::MaterialEssl1;
|
|
break;
|
|
case ShaderLanguage::ESSL3:
|
|
json << "opengl";
|
|
chunkType = ChunkType::MaterialGlsl;
|
|
break;
|
|
case ShaderLanguage::SPIRV:
|
|
json << "vulkan";
|
|
chunkType = ChunkType::MaterialSpirv;
|
|
break;
|
|
case ShaderLanguage::MSL:
|
|
json << "metal";
|
|
chunkType = ChunkType::MaterialMetal;
|
|
break;
|
|
case ShaderLanguage::WGSL:
|
|
json << "webgpu";
|
|
chunkType = ChunkType::MaterialWgsl;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
shaders.resize(getShaderCount(package, chunkType));
|
|
getShaderInfo(package, shaders.data(), chunkType);
|
|
|
|
json << "\", \"";
|
|
switch (shaderModel) {
|
|
case DbgShaderModel::DESKTOP:
|
|
json << toString(ShaderModel::DESKTOP);
|
|
break;
|
|
case DbgShaderModel::MOBILE:
|
|
json << toString(ShaderModel::MOBILE);
|
|
break;
|
|
case DbgShaderModel::MATINFO:
|
|
json << "matinfo";
|
|
break;
|
|
}
|
|
json << "\"";
|
|
|
|
for (size_t variant = 0; variant < activeVariants.size(); variant++) {
|
|
if (activeVariants[variant]) {
|
|
json << ", " << variant;
|
|
}
|
|
}
|
|
json << "]";
|
|
mJsonString = CString(json.str().c_str());
|
|
return true;
|
|
}
|
|
|
|
} // namespace matdbg
|
|
} // namespace filament
|