mirror of
https://github.com/hedge-dev/XenosRecomp.git
synced 2025-10-30 07:12:17 +00:00
Implement shader cache writing.
This commit is contained in:
parent
4ade76d7db
commit
d7350a8e1a
4 changed files with 95 additions and 40 deletions
|
|
@ -16,7 +16,11 @@ add_executable(ShaderRecomp
|
||||||
shader_recompiler.h)
|
shader_recompiler.h)
|
||||||
|
|
||||||
find_package(directx-dxc CONFIG REQUIRED)
|
find_package(directx-dxc CONFIG REQUIRED)
|
||||||
target_link_libraries(ShaderRecomp PRIVATE Microsoft::DirectXShaderCompiler)
|
find_package(xxhash CONFIG REQUIRED)
|
||||||
|
|
||||||
|
target_link_libraries(ShaderRecomp PRIVATE
|
||||||
|
Microsoft::DirectXShaderCompiler
|
||||||
|
xxHash::xxhash)
|
||||||
|
|
||||||
target_precompile_headers(ShaderRecomp PRIVATE pch.h)
|
target_precompile_headers(ShaderRecomp PRIVATE pch.h)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
#include "shader_recompiler.h"
|
#include "shader_recompiler.h"
|
||||||
#include "dxc_compiler.h"
|
#include "dxc_compiler.h"
|
||||||
|
|
||||||
static std::unique_ptr<uint8_t[]> readAllBytes(const char* filePath)
|
static std::unique_ptr<uint8_t[]> readAllBytes(const char* filePath, size_t& fileSize)
|
||||||
{
|
{
|
||||||
FILE* file = fopen(filePath, "rb");
|
FILE* file = fopen(filePath, "rb");
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
long fileSize = ftell(file);
|
fileSize = ftell(file);
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
auto data = std::make_unique<uint8_t[]>(fileSize);
|
auto data = std::make_unique<uint8_t[]>(fileSize);
|
||||||
fread(data.get(), 1, fileSize, file);
|
fread(data.get(), 1, fileSize, file);
|
||||||
|
|
@ -21,59 +21,107 @@ static void writeAllBytes(const char* filePath, const void* data, size_t dataSiz
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ShaderCacheEntry
|
||||||
|
{
|
||||||
|
XXH64_hash_t hash = 0;
|
||||||
|
uint32_t dxilOffset = 0;
|
||||||
|
uint32_t dxilSize = 0;
|
||||||
|
uint32_t spirvOffset = 0;
|
||||||
|
uint32_t spirvSize = 0;
|
||||||
|
uint64_t reserved = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShaderHolder
|
||||||
|
{
|
||||||
|
std::string filePath;
|
||||||
|
size_t fileSize = 0;
|
||||||
|
std::unique_ptr<uint8_t[]> fileData;
|
||||||
|
IDxcBlob* dxil = nullptr;
|
||||||
|
IDxcBlob* spirv = nullptr;
|
||||||
|
ShaderCacheEntry entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShaderCacheHeader
|
||||||
|
{
|
||||||
|
uint32_t version = 0;
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint32_t reserved0 = 0;
|
||||||
|
uint32_t reserved1 = 0;
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (std::filesystem::is_directory(argv[1]))
|
if (std::filesystem::is_directory(argv[1]))
|
||||||
{
|
{
|
||||||
std::vector<std::string> filePaths;
|
std::map<XXH64_hash_t, ShaderHolder> shaders;
|
||||||
|
|
||||||
for (auto& file : std::filesystem::directory_iterator(argv[1]))
|
for (auto& file : std::filesystem::directory_iterator(argv[1]))
|
||||||
{
|
{
|
||||||
auto extension = file.path().extension();
|
auto extension = file.path().extension();
|
||||||
if (extension == ".xpu" || extension == ".xvu")
|
if (extension == ".xpu" || extension == ".xvu")
|
||||||
filePaths.push_back(file.path().string());
|
{
|
||||||
|
ShaderHolder shader;
|
||||||
|
shader.filePath = file.path().string();
|
||||||
|
shader.fileData = readAllBytes(shader.filePath.c_str(), shader.fileSize);
|
||||||
|
shader.entry.hash = XXH3_64bits(shader.fileData.get(), shader.fileSize);
|
||||||
|
|
||||||
|
shaders.emplace(shader.entry.hash, std::move(shader));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::for_each(std::execution::par_unseq, filePaths.begin(), filePaths.end(), [&](auto& filePath)
|
std::for_each(std::execution::par_unseq, shaders.begin(), shaders.end(), [&](auto& hashShaderPair)
|
||||||
{
|
{
|
||||||
printf("%s\n", filePath.c_str());
|
auto& shader = hashShaderPair.second;
|
||||||
|
printf("%s\n", shader.filePath.c_str());
|
||||||
|
|
||||||
thread_local ShaderRecompiler recompiler;
|
thread_local ShaderRecompiler recompiler;
|
||||||
recompiler = {};
|
recompiler = {};
|
||||||
recompiler.recompile(readAllBytes(filePath.c_str()).get());
|
recompiler.recompile(shader.fileData.get());
|
||||||
writeAllBytes((filePath + ".hlsl").c_str(), recompiler.out.data(), recompiler.out.size());
|
writeAllBytes((shader.filePath + ".hlsl").c_str(), recompiler.out.data(), recompiler.out.size());
|
||||||
|
|
||||||
thread_local DxcCompiler dxcCompiler;
|
thread_local DxcCompiler dxcCompiler;
|
||||||
|
|
||||||
auto dxil = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false);
|
shader.dxil = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false);
|
||||||
auto spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, true);
|
shader.spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, true);
|
||||||
|
|
||||||
assert(dxil != nullptr && spirv != nullptr);
|
assert(shader.dxil != nullptr && shader.spirv != nullptr);
|
||||||
assert(*(reinterpret_cast<uint32_t*>(dxil->GetBufferPointer()) + 1) != 0 && "DXIL was not signed properly!");
|
assert(*(reinterpret_cast<uint32_t*>(shader.dxil->GetBufferPointer()) + 1) != 0 && "DXIL was not signed properly!");
|
||||||
|
|
||||||
std::string outFilePath = argv[2];
|
|
||||||
outFilePath += '/';
|
|
||||||
outFilePath += filePath.substr(filePath.find_last_of("\\/") + 1);
|
|
||||||
|
|
||||||
FILE* file = fopen(outFilePath.c_str(), "wb");
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t dxilSize;
|
|
||||||
uint32_t spirvSize;
|
|
||||||
} header;
|
|
||||||
|
|
||||||
header.version = 0;
|
|
||||||
header.dxilSize = uint32_t(dxil->GetBufferSize());
|
|
||||||
header.spirvSize = uint32_t(spirv->GetBufferSize());
|
|
||||||
|
|
||||||
fwrite(&header, sizeof(header), 1, file);
|
|
||||||
fwrite(dxil->GetBufferPointer(), 1, dxil->GetBufferSize(), file);
|
|
||||||
fwrite(spirv->GetBufferPointer(), 1, spirv->GetBufferSize(), file);
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
FILE* file = fopen(argv[2], "wb");
|
||||||
|
|
||||||
|
ShaderCacheHeader header{};
|
||||||
|
header.version = 0;
|
||||||
|
header.count = shaders.size();
|
||||||
|
fwrite(&header, sizeof(header), 1, file);
|
||||||
|
|
||||||
|
uint32_t headerSize = sizeof(ShaderCacheHeader) + shaders.size() * sizeof(ShaderCacheEntry);
|
||||||
|
uint32_t dxilOffset = headerSize;
|
||||||
|
uint32_t spirvOffset = 0;
|
||||||
|
|
||||||
|
for (auto& [_, shader] : shaders)
|
||||||
|
{
|
||||||
|
shader.entry.dxilOffset = dxilOffset;
|
||||||
|
shader.entry.dxilSize = uint32_t(shader.dxil->GetBufferSize());
|
||||||
|
shader.entry.spirvOffset = spirvOffset;
|
||||||
|
shader.entry.spirvSize = uint32_t(shader.spirv->GetBufferSize());
|
||||||
|
dxilOffset += shader.entry.dxilSize;
|
||||||
|
spirvOffset += shader.entry.spirvSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& [_, shader] : shaders)
|
||||||
|
{
|
||||||
|
shader.entry.spirvOffset += dxilOffset;
|
||||||
|
fwrite(&shader.entry, sizeof(shader.entry), 1, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& [_, shader] : shaders)
|
||||||
|
fwrite(shader.dxil->GetBufferPointer(), 1, shader.dxil->GetBufferSize(), file);
|
||||||
|
|
||||||
|
for (auto& [_, shader] : shaders)
|
||||||
|
fwrite(shader.spirv->GetBufferPointer(), 1, shader.spirv->GetBufferSize(), file);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@
|
||||||
#include <execution>
|
#include <execution>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <format>
|
#include <format>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <xxhash.h>
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct be
|
struct be
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"builtin-baseline": "e63bd09dc0b7204467705c1c7c71d0e2a3f8860b",
|
"builtin-baseline": "e63bd09dc0b7204467705c1c7c71d0e2a3f8860b",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"directx-dxc"
|
"directx-dxc",
|
||||||
]
|
"xxhash"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue