Fix OpenGL shader temp file collisions

This commit is contained in:
2026-04-09 23:44:01 +08:00
parent 681452c70e
commit 7733d59ed1
2 changed files with 125 additions and 8 deletions

View File

@@ -16,6 +16,7 @@
#include "XCEngine/RHI/RHIShader.h"
#include "XCEngine/RHI/RHISampler.h"
#include "XCEngine/RHI/RHISwapChain.h"
#include "XCEngine/RHI/ShaderCompiler/SpirvShaderCompiler.h"
#include "XCEngine/RHI/RHITexture.h"
#include <cstdint>
@@ -23,6 +24,9 @@
#include <algorithm>
#include <filesystem>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
using namespace XCEngine::RHI;
@@ -118,6 +122,87 @@ VSOutput MainVS(VSInput input) {
delete shader;
}
TEST(OpenGLShaderCompiler_Test, ParallelSpirvToolInvocationsDoNotCollideOnTemporaryFiles) {
if (!SupportsOpenGLHlslToolchainForTests()) {
GTEST_SKIP() << "glslangValidator.exe or spirv-cross.exe was not found.";
}
static const char* vertexSource = R"(
struct VSInput {
float4 position : POSITION;
};
struct VSOutput {
float4 position : SV_POSITION;
};
VSOutput MainVS(VSInput input) {
VSOutput output;
output.position = input.position;
return output;
}
)";
ShaderCompileDesc shaderDesc = {};
shaderDesc.source.assign(vertexSource, vertexSource + std::strlen(vertexSource));
shaderDesc.sourceLanguage = ShaderLanguage::HLSL;
shaderDesc.entryPoint = L"MainVS";
shaderDesc.profile = L"vs_5_0";
constexpr int kWorkerCount = 4;
constexpr int kIterationsPerWorker = 4;
std::mutex failureMutex;
std::vector<std::string> failures;
std::vector<std::thread> workers;
workers.reserve(kWorkerCount);
for (int workerIndex = 0; workerIndex < kWorkerCount; ++workerIndex) {
workers.emplace_back([&, workerIndex]() {
for (int iteration = 0; iteration < kIterationsPerWorker; ++iteration) {
CompiledSpirvShader compiledShader = {};
std::string errorMessage;
if (!CompileSpirvShader(
shaderDesc,
SpirvTargetEnvironment::Vulkan,
compiledShader,
&errorMessage)) {
std::lock_guard<std::mutex> lock(failureMutex);
failures.push_back(
"CompileSpirvShader failed for worker " +
std::to_string(workerIndex) +
", iteration " +
std::to_string(iteration) +
": " +
errorMessage);
return;
}
std::string glslSource;
errorMessage.clear();
if (!TranspileSpirvToOpenGLGLSL(compiledShader, glslSource, &errorMessage) ||
glslSource.empty()) {
std::lock_guard<std::mutex> lock(failureMutex);
failures.push_back(
"TranspileSpirvToOpenGLGLSL failed for worker " +
std::to_string(workerIndex) +
", iteration " +
std::to_string(iteration) +
": " +
errorMessage);
return;
}
}
});
}
for (std::thread& worker : workers) {
worker.join();
}
ASSERT_TRUE(failures.empty()) << failures.front();
}
TEST_F(OpenGLTestFixture, Device_CreatePipelineState_HlslGraphicsShaders_UsesTranspiledHlslPath) {
ASSERT_TRUE(GetDevice()->MakeContextCurrent());
if (!SupportsOpenGLHlslToolchainForTests()) {