Add shader artifact import pipeline

This commit is contained in:
2026-04-03 14:56:51 +08:00
parent 0f51f553c8
commit d4afa022c1
8 changed files with 1095 additions and 4 deletions

View File

@@ -59,6 +59,13 @@ void FlipLastByte(const std::filesystem::path& path) {
ASSERT_TRUE(static_cast<bool>(output));
}
void WriteTextFile(const std::filesystem::path& path, const std::string& contents) {
std::ofstream output(path, std::ios::binary | std::ios::trunc);
ASSERT_TRUE(output.is_open());
output << contents;
ASSERT_TRUE(static_cast<bool>(output));
}
TEST(MaterialLoader, GetResourceType) {
MaterialLoader loader;
EXPECT_EQ(loader.GetResourceType(), ResourceType::Material);
@@ -438,6 +445,84 @@ TEST(MaterialLoader, AssetDatabaseReimportsMaterialWhenTextureDependencyChanges)
fs::remove_all(projectRoot);
}
TEST(MaterialLoader, AssetDatabaseReimportsMaterialWhenShaderDependencyChanges) {
namespace fs = std::filesystem;
using namespace std::chrono_literals;
ResourceManager& manager = ResourceManager::Get();
manager.Initialize();
const fs::path projectRoot = fs::temp_directory_path() / "xc_material_shader_dependency_reimport_test";
const fs::path assetsDir = projectRoot / "Assets";
const fs::path shaderDir = assetsDir / "Shaders";
const fs::path shaderManifestPath = shaderDir / "lit.shader";
const fs::path materialPath = assetsDir / "textured.material";
fs::remove_all(projectRoot);
fs::create_directories(shaderDir);
WriteTextFile(shaderDir / "lit.vert.glsl", "#version 430\nvoid main() {}\n");
WriteTextFile(shaderDir / "lit.frag.glsl", "#version 430\nvoid main() {}\n");
{
std::ofstream manifest(shaderManifestPath);
ASSERT_TRUE(manifest.is_open());
manifest << "{\n";
manifest << " \"name\": \"MaterialDependencyShader\",\n";
manifest << " \"passes\": [\n";
manifest << " {\n";
manifest << " \"name\": \"ForwardLit\",\n";
manifest << " \"variants\": [\n";
manifest << " { \"stage\": \"Vertex\", \"backend\": \"OpenGL\", \"language\": \"GLSL\", \"source\": \"lit.vert.glsl\" },\n";
manifest << " { \"stage\": \"Fragment\", \"backend\": \"OpenGL\", \"language\": \"GLSL\", \"source\": \"lit.frag.glsl\" }\n";
manifest << " ]\n";
manifest << " }\n";
manifest << " ]\n";
manifest << "}\n";
}
{
std::ofstream materialFile(materialPath);
ASSERT_TRUE(materialFile.is_open());
materialFile << "{\n";
materialFile << " \"shader\": \"Assets/Shaders/lit.shader\",\n";
materialFile << " \"shaderPass\": \"ForwardLit\",\n";
materialFile << " \"renderQueue\": \"geometry\"\n";
materialFile << "}\n";
}
manager.SetResourceRoot(projectRoot.string().c_str());
AssetDatabase database;
database.Initialize(projectRoot.string().c_str());
AssetDatabase::ResolvedAsset firstResolve;
ASSERT_TRUE(database.EnsureArtifact("Assets/textured.material", ResourceType::Material, firstResolve));
ASSERT_TRUE(firstResolve.artifactReady);
const String firstArtifactPath = firstResolve.artifactMainPath;
database.Shutdown();
std::this_thread::sleep_for(50ms);
{
std::ofstream manifest(shaderManifestPath, std::ios::app);
ASSERT_TRUE(manifest.is_open());
manifest << "\n";
ASSERT_TRUE(static_cast<bool>(manifest));
}
database.Initialize(projectRoot.string().c_str());
AssetDatabase::ResolvedAsset secondResolve;
ASSERT_TRUE(database.EnsureArtifact("Assets/textured.material", ResourceType::Material, secondResolve));
ASSERT_TRUE(secondResolve.artifactReady);
EXPECT_NE(firstArtifactPath, secondResolve.artifactMainPath);
EXPECT_TRUE(fs::exists(secondResolve.artifactMainPath.CStr()));
database.Shutdown();
manager.SetResourceRoot("");
manager.Shutdown();
fs::remove_all(projectRoot);
}
TEST(MaterialLoader, LoadMaterialArtifactDefersTexturePayloadUntilRequested) {
namespace fs = std::filesystem;