blob: 2bfc0e05f6f0405aab42cf293f95b54f07fbaf6d [file] [log] [blame]
// Copyright 2022 The SwiftShader Authors. All Rights Reserved.
//
// 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 "SpirvProfiler.hpp"
#include "System/Debug.hpp"
#include "spirv-tools/libspirv.h"
#include <string.h>
#include <atomic>
#include <fstream>
namespace {
std::string GetSpvOpName(const spv::Op &op)
{
return std::string("Op") + spvOpcodeString(static_cast<uint32_t>(op));
}
std::string ConcatPath(const std::string &base, const std::string &file)
{
if(base.size() == 0)
{
return file;
}
char lastChar = *base.rend();
if(lastChar == '\\' || lastChar == '/')
{
return base + file;
}
return base + "/" + file;
}
} // namespace
namespace sw {
SpirvProfiler::SpirvProfiler(const Configuration &config)
: cfg(config)
{
reportFilePath = ConcatPath(cfg.spvProfilingReportDir, "spirv_profile.txt");
reportThreadStop = false;
reportThread = std::thread{ [this] {
while(!reportThreadStop.load(std::memory_order_acquire))
{
std::this_thread::sleep_for(std::chrono::milliseconds(cfg.spvProfilingReportPeriodMs));
ReportSnapshot();
}
} };
}
SpirvProfiler::~SpirvProfiler()
{
reportThreadStop.store(true, std::memory_order_release);
reportThread.join();
}
void SpirvProfiler::ReportSnapshot()
{
std::ofstream f{ reportFilePath };
if(!f)
{
warn("Error writing SPIR-V profile to file %s: %s\n", reportFilePath.c_str(), strerror(errno));
return;
}
auto profiles = GetRegisteredProfilesSnapshot();
for(const auto &[shaderId, profileData] : profiles)
{
f << "[Shader " << shaderId << "]" << std::endl;
f << "[SPIR-V operand execution count]" << std::endl;
for(const auto &[spvOp, execCount] : profileData->spvOpExecutionCount)
{
f << GetSpvOpName(spvOp) << ": " << execCount << std::endl;
}
f << std::endl;
}
f.close();
}
void SpirvProfiler::RegisterShaderForProfiling(std::string shaderId, std::unique_ptr<SpirvProfileData> profData)
{
marl::lock lock{ profileMux };
shaderProfiles[shaderId] = std::move(profData);
}
std::unordered_map<std::string, SpirvProfileData *> SpirvProfiler::GetRegisteredProfilesSnapshot()
{
marl::lock lock{ profileMux };
std::unordered_map<std::string, SpirvProfileData *> snapshot;
for(const auto &[shaderId, profileData] : shaderProfiles)
{
snapshot.emplace(shaderId, profileData.get());
}
return snapshot;
}
} // namespace sw