Skip to content

Commit

Permalink
matdbg: enable source formatting (#8338)
Browse files Browse the repository at this point in the history
We use clang-format to format the shader files. Since we assume
clang is necessary for compilation, installing clang-format should
not be too much of an overhead in terms of adding dependency.

Currently, we only support posix systems (macOS, linux).
poweifeng authored Jan 7, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent ef6ef78 commit a003d37
Showing 5 changed files with 137 additions and 17 deletions.
2 changes: 2 additions & 0 deletions libs/matdbg/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -31,6 +31,8 @@ set(SRCS
src/ShaderReplacer.cpp
src/ShaderExtractor.cpp
src/ShaderInfo.cpp
src/SourceFormatter.cpp
src/SourceFormatter.h
src/TextWriter.cpp
)

31 changes: 14 additions & 17 deletions libs/matdbg/src/ApiHandler.cpp
Original file line number Diff line number Diff line change
@@ -43,19 +43,6 @@ namespace {
auto const& kSuccessHeader = DebugServer::kSuccessHeader;
auto const& kErrorHeader = DebugServer::kErrorHeader;

void spirvToAsm(struct mg_connection* conn, uint32_t const* spirv, size_t size) {
auto spirvDisassembly = ShaderExtractor::spirvToText(spirv, size / 4);
mg_printf(conn, kSuccessHeader.data(), "application/txt");
mg_write(conn, spirvDisassembly.c_str(), spirvDisassembly.size());
}

void spirvToGlsl(ShaderModel shaderModel, struct mg_connection* conn, uint32_t const* spirv,
size_t size) {
auto glsl = ShaderExtractor::spirvToGLSL(shaderModel, spirv, size / 4);
mg_printf(conn, kSuccessHeader.data(), "application/txt");
mg_printf(conn, glsl.c_str(), glsl.size());
}

} // anonymous

using filaflat::ChunkContainer;
@@ -145,8 +132,10 @@ bool ApiHandler::handleGetApiShader(struct mg_connection* conn,
filaflat::ShaderContent content;
extractor.getShader(item.shaderModel, item.variant, item.pipelineStage, content);

std::string const shader = mFormatter.format((char const*) content.data());
mg_printf(conn, kSuccessHeader.data(), "application/txt");
mg_write(conn, content.data(), content.size() - 1);
mg_write(conn, shader.c_str(), shader.size());

return true;
}

@@ -171,12 +160,19 @@ bool ApiHandler::handleGetApiShader(struct mg_connection* conn,
extractor.getShader(item.shaderModel, item.variant, item.pipelineStage, content);

if (language == spirv) {
spirvToAsm(conn, (uint32_t const*) content.data(), content.size());
auto spirvDisassembly = ShaderExtractor::spirvToText((uint32_t const*) content.data(),
content.size() / 4);
mg_printf(conn, kSuccessHeader.data(), "application/txt");
mg_write(conn, spirvDisassembly.c_str(), spirvDisassembly.size());
return true;
}

if (language == glsl) {
spirvToGlsl(item.shaderModel, conn, (uint32_t const*) content.data(), content.size());
auto glsl = ShaderExtractor::spirvToGLSL(item.shaderModel,
(uint32_t const*) content.data(), content.size() / 4);
std::string const shader = mFormatter.format((char const*) glsl.c_str());
mg_printf(conn, kSuccessHeader.data(), "application/txt");
mg_printf(conn, shader.c_str(), shader.size());
return true;
}

@@ -204,8 +200,9 @@ bool ApiHandler::handleGetApiShader(struct mg_connection* conn,
extractor.getShader(item.shaderModel, item.variant, item.pipelineStage, content);

if (language == msl) {
std::string const shader = mFormatter.format((char const*) content.data());
mg_printf(conn, kSuccessHeader.data(), "application/txt");
mg_write(conn, content.data(), content.size() - 1);
mg_write(conn, shader.c_str(), shader.size());
return true;
}

4 changes: 4 additions & 0 deletions libs/matdbg/src/ApiHandler.h
Original file line number Diff line number Diff line change
@@ -17,6 +17,8 @@
#ifndef MATDBG_APIHANDLER_H
#define MATDBG_APIHANDLER_H

#include "SourceFormatter.h"

#include <mutex>
#include <condition_variable>
#include <atomic>
@@ -63,6 +65,8 @@ class ApiHandler : public CivetHandler {
// will always block until statusMaterialId is updated again. The client is expected to keep
// calling /api/status (a constant "pull" to simulate a push).
std::atomic<uint64_t> mCurrentStatus = 0;

SourceFormatter mFormatter;
};

} // filament::matdbg
80 changes: 80 additions & 0 deletions libs/matdbg/src/SourceFormatter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2025 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 "SourceFormatter.h"

#include <utils/Log.h>

#include <cstdio>
#include <sstream>

namespace filament::matdbg {

#if defined(__linux__) || defined(__APPLE__)
std::string SourceFormatter::format(char const* source) {
std::string const TMP_FILENAME = "/tmp/matdbg-tmp-src.cpp";

std::string original(source);
FILE* fp;
fp = fopen(TMP_FILENAME.c_str(), "w");
if (!fp) {
return original;
}
fputs(original.c_str(), fp);
fflush(fp);
pclose(fp);

std::string const CLANG_FORMAT_OPTIONS =
"-style='{"
"BasedOnStyle: Google, "
"IndentWidth: 4, "
"MaxEmptyLinesToKeep: 2"
"}'";

fp = popen(("clang-format " + CLANG_FORMAT_OPTIONS + "< " + TMP_FILENAME).c_str(), "r");

if (!fp) {
std::call_once(mClangWarningFlag, []() {
utils::slog.w << "[matdbg] unable to run clang-format to format shader file. "
<< "Please make sure it's installed.";
});
return original;
}

char output[1024];
std::stringstream outStream;
while (fgets(output, 1024, fp) != NULL) {
outStream << output;
}

int status = pclose(fp);
if (WEXITSTATUS(status)) {
utils::slog.w << "[matdbg] clang-format failed with code=" << WEXITSTATUS(status)
<< utils::io::endl;
}
return outStream.str();
}
#else
std::string SourceFormatter::format(char const* source) {
std::call_once(mClangWarningFlag, []() {
utils::slog.w <<"[matdbg]: source formatting is not available on this platform" <<
utils::io::endl;
});
return "";
}
#endif

} // filament::matdbg
37 changes: 37 additions & 0 deletions libs/matdbg/src/SourceFormatter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2025 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.
*/

#ifndef MATDBG_SOURCE_FORMATTER_H
#define MATDBG_SOURCE_FORMATTER_H

#include <mutex>

namespace filament::matdbg {

class SourceFormatter {
public:
SourceFormatter() = default;
~SourceFormatter() = default;
std::string format(char const* source);

private:

std::once_flag mClangWarningFlag;
};

} // filament::matdbg

#endif // MATDBG_SOURCE_FORMATTER_H

0 comments on commit a003d37

Please sign in to comment.