This commit is contained in:
2026-05-03 11:16:56 +10:00
parent f6db9ee3e6
commit ee929374a8
14 changed files with 873 additions and 350 deletions

View File

@@ -1,7 +1,8 @@
#include "stdafx.h"
#include "ShaderCompiler.h"
#include <cstring>
#include "NativeHandles.h"
#include <fstream>
#include <regex>
#include <sstream>
@@ -20,17 +21,51 @@ std::string ReplaceAll(std::string text, const std::string& from, const std::str
return text;
}
std::string SlangTypeForParameter(ShaderParameterType type)
std::string SlangCBufferTypeForParameter(ShaderParameterType type)
{
switch (type)
{
case ShaderParameterType::Float: return "uniform float";
case ShaderParameterType::Vec2: return "uniform float2";
case ShaderParameterType::Color: return "uniform float4";
case ShaderParameterType::Boolean: return "uniform bool";
case ShaderParameterType::Enum: return "uniform int";
case ShaderParameterType::Float: return "float";
case ShaderParameterType::Vec2: return "float2";
case ShaderParameterType::Color: return "float4";
case ShaderParameterType::Boolean: return "bool";
case ShaderParameterType::Enum: return "int";
}
return "uniform float";
return "float";
}
std::string BuildParameterUniforms(const std::vector<ShaderParameterDefinition>& parameters)
{
std::ostringstream source;
for (const ShaderParameterDefinition& definition : parameters)
source << "\t" << SlangCBufferTypeForParameter(definition.type) << " " << definition.id << ";\n";
return source.str();
}
std::string BuildHistorySamplerDeclarations(const std::string& samplerPrefix, unsigned historyLength)
{
std::ostringstream source;
for (unsigned index = 0; index < historyLength; ++index)
source << "Sampler2D<float4> " << samplerPrefix << index << ";\n";
return source.str();
}
std::string BuildTextureSamplerDeclarations(const std::vector<ShaderTextureAsset>& textureAssets)
{
std::ostringstream source;
for (const ShaderTextureAsset& textureAsset : textureAssets)
source << "Sampler2D<float4> " << textureAsset.id << ";\n";
if (!textureAssets.empty())
source << "\n";
return source.str();
}
std::string BuildHistorySwitchCases(const std::string& samplerPrefix, unsigned historyLength)
{
std::ostringstream source;
for (unsigned index = 0; index < historyLength; ++index)
source << "\tcase " << index << ": return " << samplerPrefix << index << ".Sample(tc);\n";
return source.str();
}
}
@@ -50,7 +85,9 @@ ShaderCompiler::ShaderCompiler(
bool ShaderCompiler::BuildLayerFragmentShaderSource(const ShaderPackage& shaderPackage, std::string& fragmentShaderSource, std::string& error) const
{
const std::string wrapperSource = BuildWrapperSlangSource(shaderPackage);
std::string wrapperSource;
if (!BuildWrapperSlangSource(shaderPackage, wrapperSource, error))
return false;
if (!WriteTextFile(mWrapperPath, wrapperSource, error))
return false;
@@ -70,104 +107,22 @@ bool ShaderCompiler::BuildLayerFragmentShaderSource(const ShaderPackage& shaderP
return true;
}
std::string ShaderCompiler::BuildWrapperSlangSource(const ShaderPackage& shaderPackage) const
bool ShaderCompiler::BuildWrapperSlangSource(const ShaderPackage& shaderPackage, std::string& wrapperSource, std::string& error) const
{
std::ostringstream source;
source << "struct FragmentInput\n";
source << "{\n";
source << "\tfloat4 position : SV_Position;\n";
source << "\tfloat2 texCoord : TEXCOORD0;\n";
source << "};\n\n";
source << "struct ShaderContext\n";
source << "{\n";
source << "\tfloat2 uv;\n";
source << "\tfloat4 sourceColor;\n";
source << "\tfloat2 inputResolution;\n";
source << "\tfloat2 outputResolution;\n";
source << "\tfloat time;\n";
source << "\tfloat frameCount;\n";
source << "\tfloat mixAmount;\n";
source << "\tfloat bypass;\n";
source << "\tint sourceHistoryLength;\n";
source << "\tint temporalHistoryLength;\n";
source << "};\n\n";
source << "cbuffer GlobalParams\n";
source << "{\n";
source << "\tfloat gTime;\n";
source << "\tfloat2 gInputResolution;\n";
source << "\tfloat2 gOutputResolution;\n";
source << "\tfloat gFrameCount;\n";
source << "\tfloat gMixAmount;\n";
source << "\tfloat gBypass;\n";
source << "\tint gSourceHistoryLength;\n";
source << "\tint gTemporalHistoryLength;\n";
for (const ShaderParameterDefinition& definition : shaderPackage.parameters)
source << "\t" << SlangTypeForParameter(definition.type).substr(strlen("uniform ")) << " " << definition.id << ";\n";
source << "};\n\n";
source << "Sampler2D<float4> gVideoInput;\n";
for (unsigned index = 0; index < mMaxTemporalHistoryFrames; ++index)
source << "Sampler2D<float4> gSourceHistory" << index << ";\n";
for (unsigned index = 0; index < mMaxTemporalHistoryFrames; ++index)
source << "Sampler2D<float4> gTemporalHistory" << index << ";\n";
for (const ShaderTextureAsset& textureAsset : shaderPackage.textureAssets)
source << "Sampler2D<float4> " << textureAsset.id << ";\n";
source << "\n";
source << "float4 sampleVideo(float2 tc)\n";
source << "{\n";
source << "\treturn gVideoInput.Sample(tc);\n";
source << "}\n\n";
source << "float4 sampleSourceHistory(int framesAgo, float2 tc)\n";
source << "{\n";
source << "\tif (gSourceHistoryLength <= 0)\n";
source << "\t\treturn sampleVideo(tc);\n";
source << "\tint clampedIndex = framesAgo;\n";
source << "\tif (clampedIndex < 0)\n";
source << "\t\tclampedIndex = 0;\n";
source << "\tif (clampedIndex >= gSourceHistoryLength)\n";
source << "\t\tclampedIndex = gSourceHistoryLength - 1;\n";
source << "\tswitch (clampedIndex)\n";
source << "\t{\n";
for (unsigned index = 0; index < mMaxTemporalHistoryFrames; ++index)
source << "\tcase " << index << ": return gSourceHistory" << index << ".Sample(tc);\n";
source << "\tdefault: return sampleVideo(tc);\n";
source << "\t}\n";
source << "}\n\n";
source << "float4 sampleTemporalHistory(int framesAgo, float2 tc)\n";
source << "{\n";
source << "\tif (gTemporalHistoryLength <= 0)\n";
source << "\t\treturn sampleVideo(tc);\n";
source << "\tint clampedIndex = framesAgo;\n";
source << "\tif (clampedIndex < 0)\n";
source << "\t\tclampedIndex = 0;\n";
source << "\tif (clampedIndex >= gTemporalHistoryLength)\n";
source << "\t\tclampedIndex = gTemporalHistoryLength - 1;\n";
source << "\tswitch (clampedIndex)\n";
source << "\t{\n";
for (unsigned index = 0; index < mMaxTemporalHistoryFrames; ++index)
source << "\tcase " << index << ": return gTemporalHistory" << index << ".Sample(tc);\n";
source << "\tdefault: return sampleVideo(tc);\n";
source << "\t}\n";
source << "}\n\n";
source << "#include \"" << shaderPackage.shaderPath.generic_string() << "\"\n\n";
source << "[shader(\"fragment\")]\n";
source << "float4 fragmentMain(FragmentInput input) : SV_Target\n";
source << "{\n";
source << "\tShaderContext context;\n";
source << "\tcontext.uv = input.texCoord;\n";
source << "\tcontext.sourceColor = sampleVideo(context.uv);\n";
source << "\tcontext.inputResolution = gInputResolution;\n";
source << "\tcontext.outputResolution = gOutputResolution;\n";
source << "\tcontext.time = gTime;\n";
source << "\tcontext.frameCount = gFrameCount;\n";
source << "\tcontext.mixAmount = gMixAmount;\n";
source << "\tcontext.bypass = gBypass;\n";
source << "\tcontext.sourceHistoryLength = gSourceHistoryLength;\n";
source << "\tcontext.temporalHistoryLength = gTemporalHistoryLength;\n";
source << "\tfloat4 effectedColor = " << shaderPackage.entryPoint << "(context);\n";
source << "\tfloat mixValue = clamp(gBypass > 0.5 ? 0.0 : gMixAmount, 0.0, 1.0);\n";
source << "\treturn lerp(context.sourceColor, effectedColor, mixValue);\n";
source << "}\n";
return source.str();
const std::filesystem::path templatePath = mRepoRoot / "runtime" / "templates" / "shader_wrapper.slang.in";
wrapperSource = ReadTextFile(templatePath, error);
if (wrapperSource.empty())
return false;
wrapperSource = ReplaceAll(wrapperSource, "{{PARAMETER_UNIFORMS}}", BuildParameterUniforms(shaderPackage.parameters));
wrapperSource = ReplaceAll(wrapperSource, "{{SOURCE_HISTORY_SAMPLERS}}", BuildHistorySamplerDeclarations("gSourceHistory", mMaxTemporalHistoryFrames));
wrapperSource = ReplaceAll(wrapperSource, "{{TEMPORAL_HISTORY_SAMPLERS}}", BuildHistorySamplerDeclarations("gTemporalHistory", mMaxTemporalHistoryFrames));
wrapperSource = ReplaceAll(wrapperSource, "{{TEXTURE_SAMPLERS}}", BuildTextureSamplerDeclarations(shaderPackage.textureAssets));
wrapperSource = ReplaceAll(wrapperSource, "{{SOURCE_HISTORY_SWITCH_CASES}}", BuildHistorySwitchCases("gSourceHistory", mMaxTemporalHistoryFrames));
wrapperSource = ReplaceAll(wrapperSource, "{{TEMPORAL_HISTORY_SWITCH_CASES}}", BuildHistorySwitchCases("gTemporalHistory", mMaxTemporalHistoryFrames));
wrapperSource = ReplaceAll(wrapperSource, "{{USER_SHADER_INCLUDE}}", shaderPackage.shaderPath.generic_string());
wrapperSource = ReplaceAll(wrapperSource, "{{ENTRY_POINT_CALL}}", shaderPackage.entryPoint + "(context)");
return true;
}
bool ShaderCompiler::FindSlangCompiler(std::filesystem::path& compilerPath, std::string& error) const
@@ -216,12 +171,13 @@ bool ShaderCompiler::RunSlangCompiler(const std::filesystem::path& wrapperPath,
return false;
}
WaitForSingleObject(processInfo.hProcess, INFINITE);
UniqueHandle processHandle(processInfo.hProcess);
UniqueHandle threadHandle(processInfo.hThread);
WaitForSingleObject(processHandle.get(), INFINITE);
DWORD exitCode = 0;
GetExitCodeProcess(processInfo.hProcess, &exitCode);
CloseHandle(processInfo.hThread);
CloseHandle(processInfo.hProcess);
GetExitCodeProcess(processHandle.get(), &exitCode);
if (exitCode != 0)
{