/* * 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 #include #include #include #include #include "CommonWriter.h" #include #include #include 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 static void printChunk(ostream& json, const ChunkContainer& container, ChunkType type, const char* title) { T value; if (read(container, type, reinterpret_cast(&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(json, container, MaterialShading, "model"); printChunk(json, container, ChunkType::MaterialDomain, "material_domain"); printChunk(json, container, ChunkType::MaterialVariantFilterMask, "variant_filter_mask"); printChunk(json, container, MaterialVertexDomain, "vertex_domain"); printChunk(json, container, MaterialInterpolation, "interpolation"); printChunk(json, container, MaterialShadowMultiplier, "shadow_multiply"); printChunk(json, container, MaterialSpecularAntiAliasing, "specular_antialiasing"); printFloatChunk(json, container, MaterialSpecularAntiAliasingVariance, "variance"); printFloatChunk(json, container, MaterialSpecularAntiAliasingThreshold, "threshold"); printChunk(json, container, MaterialClearCoatIorChange, "clear_coat_IOR_change"); json << "\"_\": 0 },\n"; json << "\"raster\": {\n"; printChunk(json, container, MaterialBlendingMode, "blending"); printFloatChunk(json, container, MaterialMaskThreshold, "mask_threshold"); printChunk(json, container, MaterialColorWrite, "color_write"); printChunk(json, container, MaterialDepthWrite, "depth_write"); printChunk(json, container, MaterialDepthTest, "depth_test"); printChunk(json, container, MaterialInstanced, "instanced"); printChunk(json, container, MaterialDoubleSided, "double_sided"); printChunk(json, container, MaterialCullingMode, "culling"); printChunk(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& info, const ChunkContainer& container) { MaterialDomain domain = MaterialDomain::SURFACE; read(container, ChunkType::MaterialDomain, reinterpret_cast(&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 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 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 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 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(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 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