Files
SDL3CPlusPlus/MaterialX/source/MaterialXRenderSlang/SlangShaderCache.cpp
2026-01-06 13:25:49 +00:00

100 lines
2.8 KiB
C++

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#include <MaterialXRenderSlang/SlangShaderCache.h>
#include <fstream>
MATERIALX_NAMESPACE_BEGIN
namespace
{
std::string encodeBase64(const void* data, const size_t size)
{
static std::string base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
//const uint8_t* input = reinterpret_cast<const uint8_t*>(data);
std::vector<uint8_t> input(reinterpret_cast<const uint8_t*>(data), reinterpret_cast<const uint8_t*>(data) + size);
std::string result;
for (size_t i = 0; i < size; i += 3)
{
/// Split next 3 characters to 4 groups of 6 bits.
/// If there is no input character, leave the -1 placeholder.
int32_t values[4] = {-1,-1,-1,-1};
values[0] = (input[i] >> 2) & 0b00111111;
values[1] = (input[i] << 4) & 0b00110000;
if (i + 1 < size)
{
values[1] += (input[i + 1] >> 4) & 0b00001111;
values[2] += (input[i + 1] << 2) & 0b00111100;
}
if (i + 2 < size)
{
values[2] += (input[i + 2] >> 6) & 0b00000011;
values[3] += (input[i + 2]) & 0b00111111;
}
/// Encode valid characters, replace placeholders with =
for (int j = 0; j < 4; ++j)
result.push_back(values[j] >= 0 ? base64[values[j]] : '=');
}
return result;
}
} // namespace
SlangShaderCache::SlangShaderCache(const FilePath& cachePath) :
_cachePath(cachePath)
{
_cachePath.createDirectory();
}
rhi::Result SlangShaderCache::writeCache(ISlangBlob* key, ISlangBlob* data)
{
std::string filename = encodeBase64(key->getBufferPointer(), key->getBufferSize());
filename += ".slangcache";
FilePath path = _cachePath / filename;
std::ofstream ofs(path, std::ios::binary);
if (!ofs)
return SLANG_E_NOT_FOUND;
ofs.write((const char*) data->getBufferPointer(),
data->getBufferSize());
return SLANG_OK;
}
rhi::Result SlangShaderCache::queryCache(ISlangBlob* key, ISlangBlob** outData)
{
std::string filename = encodeBase64(key->getBufferPointer(), key->getBufferSize());
filename += ".slangcache";
FilePath path = _cachePath / filename;
std::ifstream ifs(path, std::ios::binary);
if (!ifs)
{
*outData = nullptr;
return SLANG_E_NOT_FOUND;
}
ifs.seekg(0, std::ios::end);
size_t length = ifs.tellg();
ifs.seekg(0, std::ios::beg);
rhi::ComPtr<ISlangBlob> blob = rhi::getRHI()->createBlob(nullptr, length);
ifs.read((char*)blob->getBufferPointer(), blob->getBufferSize());
ifs.close();
*outData = blob.detach();
return SLANG_OK;
}
MATERIALX_NAMESPACE_END