feat: 新版 FX 解析器 (p6)

This commit is contained in:
Xu 2026-03-30 17:10:41 +08:00
commit 22a3545b49
11 changed files with 385 additions and 174 deletions

View file

@ -2,8 +2,7 @@
// 移植自 https://github.com/TianZerL/ACNetGLSL/blob/f20a6b6b7327f4caf588b06c6b21f18e40dae1ce/glsl/ACNet.glsl
//!MAGPIE EFFECT
//!VERSION 4
//!USE MulAdd
//!VERSION 5
//!CAPABILITY FP16
#include "StubDefs.hlsli"
@ -13,8 +12,6 @@
Texture2D INPUT;
//!TEXTURE
//!WIDTH INPUT_WIDTH * 2
//!HEIGHT INPUT_HEIGHT * 2
Texture2D OUTPUT;
//!TEXTURE

View file

@ -1,42 +1,8 @@
#pragma once
#include <cstdint>
#include <dxgi.h>
namespace Magpie {
struct EffectHelper {
struct EffectIntermediateTextureFormatDesc {
const char* name;
DXGI_FORMAT dxgiFormat;
uint32_t nChannel;
const char* srvTexelType;
const char* uavTexelType;
};
static constexpr EffectIntermediateTextureFormatDesc FORMAT_DESCS[] = {
{"R32G32B32A32_FLOAT", DXGI_FORMAT_R32G32B32A32_FLOAT, 4, "float4", "float4"},
{"R16G16B16A16_FLOAT", DXGI_FORMAT_R16G16B16A16_FLOAT, 4, "MF4", "MF4"},
{"R16G16B16A16_UNORM", DXGI_FORMAT_R16G16B16A16_UNORM, 4, "MF4", "unorm MF4"},
{"R16G16B16A16_SNORM", DXGI_FORMAT_R16G16B16A16_SNORM, 4, "MF4", "snorm MF4"},
{"R32G32_FLOAT", DXGI_FORMAT_R32G32_FLOAT, 2, "float2", "float2"},
{"R10G10B10A2_UNORM", DXGI_FORMAT_R10G10B10A2_UNORM, 4, "MF4", "unorm MF4"},
{"R11G11B10_FLOAT", DXGI_FORMAT_R11G11B10_FLOAT, 3, "MF3", "MF3"},
{"R8G8B8A8_UNORM", DXGI_FORMAT_R8G8B8A8_UNORM, 4, "MF4", "unorm MF4"},
{"R8G8B8A8_SNORM", DXGI_FORMAT_R8G8B8A8_SNORM, 4, "MF4", "snorm MF4"},
{"R16G16_FLOAT", DXGI_FORMAT_R16G16_FLOAT, 2, "MF2", "MF2"},
{"R16G16_UNORM", DXGI_FORMAT_R16G16_UNORM, 2, "MF2", "unorm MF2"},
{"R16G16_SNORM", DXGI_FORMAT_R16G16_SNORM, 2, "MF2", "snorm MF2"},
{"R32_FLOAT" ,DXGI_FORMAT_R32_FLOAT, 1, "float", "float"},
{"R8G8_UNORM", DXGI_FORMAT_R8G8_UNORM, 2, "MF2", "unorm MF2"},
{"R8G8_SNORM", DXGI_FORMAT_R8G8_SNORM, 2, "MF2", "snorm MF2"},
{"R16_FLOAT", DXGI_FORMAT_R16_FLOAT, 1, "MF", "MF"},
{"R16_UNORM", DXGI_FORMAT_R16_UNORM, 1, "MF", "unorm MF"},
{"R16_SNORM", DXGI_FORMAT_R16_SNORM,1, "MF", "snorm MF"},
{"R8_UNORM", DXGI_FORMAT_R8_UNORM, 1, "MF", "unorm MF"},
{"R8_SNORM", DXGI_FORMAT_R8_SNORM, 1, "MF", "snorm MF"},
{"UNKNOWN", DXGI_FORMAT_UNKNOWN, 4, "float4", "float4"}
};
struct ShaderEffectTextureFormatDesc {
const char* name;
DXGI_FORMAT dxgiFormat;

View file

@ -68,8 +68,9 @@ winrt::fire_and_forget EffectsService::Initialize() {
}
auto lock = srwLock.lock_exclusive();
_effectsMap.emplace(effectInfo.name, (uint32_t)_effects.size());
_effects.emplace_back(std::move(effectInfo));
uint32_t effectIdx = (uint32_t)_effects.size();
EffectInfo& movedEffectInfo = _effects.emplace_back(std::move(effectInfo));
_effectsMap.emplace(movedEffectInfo.name, effectIdx);
}, nEffect);
_initialized.store(true, std::memory_order_release);
@ -174,7 +175,7 @@ std::string EffectsService::SubmitCompileShaderEffectTask(
if (!_shaderEffectCache.contains(cacheKey)) {
// _shaderEffectCache.emplace(cacheKey, _ShaderEffectMemCacheItem{});
ShaderEffectDesc effectDesc;
ShaderEffectDrawInfo effectDesc;
ShaderEffectSource effectSource;
std::string errorMsg = ShaderEffectParser::ParseForDesc(
effectInfo,
@ -194,7 +195,7 @@ std::string EffectsService::SubmitCompileShaderEffectTask(
return cacheKey;
}
bool EffectsService::GetTaskResult(std::string taskKey, const ShaderEffectDesc*& effectDesc) noexcept {
bool EffectsService::GetTaskResult(std::string taskKey, const ShaderEffectDrawInfo** effectDesc) noexcept {
auto it = _shaderEffectCache.find(taskKey);
if (it == _shaderEffectCache.end()) {
// 编译失败
@ -203,11 +204,12 @@ bool EffectsService::GetTaskResult(std::string taskKey, const ShaderEffectDesc*&
if (it->second.lastAccess == std::numeric_limits<uint32_t>::max()) {
// 尚未编译完成
effectDesc = nullptr;
*effectDesc = nullptr;
return true;
}
return &it->second.effectDesc;
*effectDesc = &it->second.effectDesc;
return true;
}
void EffectsService::CleanCache(bool /*clearAll*/) noexcept {

View file

@ -69,7 +69,7 @@
<ClInclude Include="include\EffectsService.h" />
<ClInclude Include="include\LocalizationService.h" />
<ClInclude Include="ShaderEffectCompilerService.h" />
<ClInclude Include="ShaderEffectDesc.h" />
<ClInclude Include="ShaderEffectDrawInfo.h" />
<ClInclude Include="ShaderEffectDrawer.h" />
<ClInclude Include="GraphicsCaptureFrameSource.h" />
<ClInclude Include="D3D12Context.h" />

View file

@ -106,9 +106,6 @@
<ClInclude Include="ShaderEffectCompilerService.h">
<Filter>Services</Filter>
</ClInclude>
<ClInclude Include="ShaderEffectDesc.h">
<Filter>EffectDrawer</Filter>
</ClInclude>
<ClInclude Include="CursorHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
@ -134,6 +131,7 @@
<ClInclude Include="Renderer.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="ShaderEffectDrawInfo.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ScalingRuntime.cpp" />

View file

@ -4,7 +4,7 @@
namespace Magpie {
bool ShaderEffectCompilerService::Submit(std::string_view /*name*/, ShaderEffectDesc& /*desc*/) const noexcept {
bool ShaderEffectCompilerService::Submit(std::string_view /*name*/, ShaderEffectDrawInfo& /*desc*/) const noexcept {
return false;
}

View file

@ -1,5 +1,5 @@
#pragma once
#include "ShaderEffectDesc.h"
#include "ShaderEffectDrawInfo.h"
namespace Magpie {
@ -13,7 +13,7 @@ public:
ShaderEffectCompilerService(const ShaderEffectCompilerService&) = delete;
ShaderEffectCompilerService(ShaderEffectCompilerService&&) = delete;
bool Submit(std::string_view name, ShaderEffectDesc& desc) const noexcept;
bool Submit(std::string_view name, ShaderEffectDrawInfo& desc) const noexcept;
private:
ShaderEffectCompilerService() = default;

View file

@ -22,24 +22,27 @@ enum class ShaderEffectTextureFormat {
};
struct ShaderEffectTextureDesc {
std::string name;
ShaderEffectTextureFormat format = ShaderEffectTextureFormat::UNKNOWN;
std::pair<std::string, std::string> sizeExpr;
std::string widthExpr;
std::string heightExpr;
std::string source;
};
enum class EffectSamplerFilterType {
enum class ShaderEffectSamplerFilterType {
Point,
Linear
};
enum class EffectSamplerAddressType {
enum class ShaderEffectSamplerAddressType {
Clamp,
Wrap
};
struct ShaderEffectSamplerDesc {
EffectSamplerFilterType filterType = EffectSamplerFilterType::Point;
EffectSamplerAddressType addressType = EffectSamplerAddressType::Clamp;
std::string name;
ShaderEffectSamplerFilterType filterType = ShaderEffectSamplerFilterType::Point;
ShaderEffectSamplerAddressType addressType = ShaderEffectSamplerAddressType::Clamp;
};
enum class ShaderEffectPassFlags {
@ -63,7 +66,7 @@ struct ShaderEffectPassDesc {
std::string desc;
};
struct ShaderEffectDesc {
struct ShaderEffectDrawInfo {
// 不包含 INPUT 和 OUTPUT
SmallVector<ShaderEffectTextureDesc, 0> textures;
SmallVector<ShaderEffectSamplerDesc> samplers;

View file

@ -1,10 +1,11 @@
#include "pch.h"
#include "ShaderEffectParser.h"
#include "EffectHelper.h"
#include "EffectInfo.h"
#include "StrHelper.h"
#include "Logger.h"
#include "ShaderEffectDesc.h"
#include "LocalizationService.h"
#include "Logger.h"
#include "ShaderEffectDrawInfo.h"
#include "ShaderEffectParser.h"
#include "StrHelper.h"
#include <bitset>
namespace Magpie {
@ -237,7 +238,7 @@ static bool CheckNextToken(std::string_view& source, ParserState& state, std::st
if (token == expectedToken) {
return true;
} else {
SetGeneralParseError(state, source, expectedToken);
SetGeneralParseError(state, token, expectedToken);
return false;
}
}
@ -267,6 +268,17 @@ static bool RequireLineEnd(std::string_view& source, ParserState& state) noexcep
}
}
static bool RequireSourceEnd(std::string_view& source, ParserState& state) noexcept {
RemoveLeadingBlanks(source, state);
if (source.empty()) {
return true;
} else {
SetGeneralParseError(state, source, "\n");
return false;
}
}
static bool CheckMagic(std::string_view& source, ParserState& state) noexcept {
bool isMetaIndicator = false;
if (!CheckMetaIndicator(source, state, isMetaIndicator)) {
@ -341,6 +353,61 @@ static bool GetNextNumber(std::string_view& source, ParserState& state, T& value
return true;
}
template <typename Fn>
static bool FindBlocks(
std::string_view sourceView,
const Fn& completeCurrentBlock,
ParserState& state
) noexcept {
for (size_t i = 0; i < sourceView.size(); ++i) {
char c = sourceView[i];
if (c == '\n') {
++state.lineNumber;
state.isNewLine = true;
} else if (c == '/') {
bool isComment;
bool isMetaIdicator;
if (!RemoveLeadingComment(sourceView, state, i, isComment, isMetaIdicator)) {
return false;
}
if (isMetaIdicator) {
std::string_view tempSource = sourceView.substr(i + 3);
std::string_view token;
if (!GetNextToken<false, false>(tempSource, state, token)) {
return false;
}
std::string newBlockType = StrHelper::ToUpperCase(token);
size_t newBlockOffset = tempSource.data() - sourceView.data();
// sourceView[i - 1] 是换行符,因此每个区块都以换行结尾。区块开头不包含声明该区块的
// 指令,如果该指令没有参数,此区块就以换行符开头。
if (newBlockType == "PARAMETER") {
completeCurrentBlock(BlockType::Parameter, i, newBlockOffset);
} else if (newBlockType == "TEXTURE") {
completeCurrentBlock(BlockType::Texture, i, newBlockOffset);
} else if (newBlockType == "SAMPLER") {
completeCurrentBlock(BlockType::Sampler, i, newBlockOffset);
} else if (newBlockType == "COMMON") {
completeCurrentBlock(BlockType::Common, i, newBlockOffset);
} else if (newBlockType == "PASS") {
completeCurrentBlock(BlockType::Pass, i, newBlockOffset);
}
// 下个循环会加一
i = newBlockOffset - 1;
state.isNewLine = false;
}
}
}
// 结束最后一个区块。sourceView 以换行符结尾,因此最后一个区块也以换行符结尾。
completeCurrentBlock(BlockType::Header, sourceView.size(), std::numeric_limits<size_t>::max());
return true;
}
struct CommandInfo {
const char* name;
bool (*resolver)(std::string_view&, ParserState&, void*) noexcept;
@ -422,11 +489,7 @@ static bool ResolveHeaderVersion(
return false;
}
if (!RequireLineEnd(source, state)) {
return false;
}
return true;
return RequireLineEnd(source, state);
}
static bool ResolveHeaderSortName(
@ -533,14 +596,10 @@ static bool ResolveHeaderScaleFactor(
return false;
}
if (!RequireLineEnd(source, state)) {
return false;
}
return true;
return RequireLineEnd(source, state);
}
static bool ResolveHeader(
static bool ResolveHeaderBlock(
std::string_view source,
ParserState& state,
EffectInfo& effectInfo
@ -577,17 +636,7 @@ static bool ResolveHeader(
return false;
}
// 之后不允许有内容
if (!RemoveLeadingBlanks(source, state)) {
return false;
}
if (!source.empty()) {
SetGeneralParseError(state, source, "\n");
return false;
}
return true;
return RequireSourceEnd(source, state);
}
static bool ResolveParameterDefault(
@ -599,11 +648,7 @@ static bool ResolveParameterDefault(
return false;
}
if (!RequireLineEnd(source, state)) {
return false;
}
return true;
return RequireLineEnd(source, state);
}
static bool ResolveParameterMin(
@ -615,11 +660,7 @@ static bool ResolveParameterMin(
return false;
}
if (!RequireLineEnd(source, state)) {
return false;
}
return true;
return RequireLineEnd(source, state);
}
static bool ResolveParameterMax(
@ -631,11 +672,7 @@ static bool ResolveParameterMax(
return false;
}
if (!RequireLineEnd(source, state)) {
return false;
}
return true;
return RequireLineEnd(source, state);
}
static bool ResolveParameterStep(
@ -647,11 +684,7 @@ static bool ResolveParameterStep(
return false;
}
if (!RequireLineEnd(source, state)) {
return false;
}
return true;
return RequireLineEnd(source, state);
}
static bool ResolveParameterLabel(
@ -668,7 +701,7 @@ static bool ResolveParameterLabel(
return true;
}
static bool ResolveParameter(
static bool ResolveParameterBlock(
std::string_view source,
ParserState& state,
EffectInfoParameter& effectInfoParameter
@ -697,7 +730,7 @@ static bool ResolveParameter(
}
if (token != "float" && token != "int") {
SetGeneralParseError(state, source, "float|int");
SetGeneralParseError(state, token, "float|int");
return false;
}
@ -719,72 +752,249 @@ static bool ResolveParameter(
source.remove_prefix(1);
state.isNewLine = false;
// 之后不允许有内容
if (!RemoveLeadingBlanks(source, state)) {
return false;
}
if (!source.empty()) {
SetGeneralParseError(state, source, "\n");
return RequireSourceEnd(source, state);
}
static bool ResolveTextureWidth(
std::string_view& source,
ParserState& state,
void* data
) noexcept {
std::string_view expr;
if (!GetNextStringUntilLineEnd<false>(source, state, expr)) {
return false;
}
((ShaderEffectTextureDesc*)data)->widthExpr = expr;
return true;
}
template <typename Fn>
static bool ResolveBlocks(
std::string_view sourceView,
const Fn& completeCurrentBlock,
ParserState& state
static bool ResolveTextureHeight(
std::string_view& source,
ParserState& state,
void* data
) noexcept {
for (size_t i = 0; i < sourceView.size(); ++i) {
char c = sourceView[i];
std::string_view expr;
if (!GetNextStringUntilLineEnd<false>(source, state, expr)) {
return false;
}
if (c == '\n') {
++state.lineNumber;
state.isNewLine = true;
} else if (c == '/') {
bool isComment;
bool isMetaIdicator;
if (!RemoveLeadingComment(sourceView, state, i, isComment, isMetaIdicator)) {
((ShaderEffectTextureDesc*)data)->heightExpr = expr;
return true;
}
static bool ResolveTextureFormat(
std::string_view& source,
ParserState& state,
void* data
) noexcept {
std::string_view token;
if (!GetNextToken<false, false>(source, state, token)) {
return false;
}
static const auto formatMap = [] {
phmap::flat_hash_map<std::string, ShaderEffectTextureFormat> result;
// UNKNOWN 不可用
constexpr size_t descCount = std::size(EffectHelper::SHADER_TEXTURE_FORMAT_DESCS) - 1;
result.reserve(descCount);
for (size_t i = 1; i < descCount; ++i) {
result.emplace(
EffectHelper::SHADER_TEXTURE_FORMAT_DESCS[i].name,
(ShaderEffectTextureFormat)i
);
}
return result;
}();
auto it = formatMap.find(StrHelper::ToUpperCase(token));
if (it == formatMap.end()) {
SetGeneralParseError(state, token);
return false;
}
((ShaderEffectTextureDesc*)data)->format = it->second;
return RequireLineEnd(source, state);
}
static bool ResolveTextureSource(
std::string_view& source,
ParserState& state,
void* data
) noexcept {
std::string_view value;
if (!GetNextStringUntilLineEnd<false>(source, state, value)) {
return false;
}
((ShaderEffectTextureDesc*)data)->source = value;
return true;
}
static bool ResolveTextureBlock(
std::string_view source,
ParserState& state,
ShaderEffectTextureDesc& desc
) noexcept {
static constexpr std::array COMMAND_INFOS = {
CommandInfo{ "WIDTH", ResolveTextureWidth, false },
CommandInfo{ "HEIGHT", ResolveTextureHeight, false },
CommandInfo{ "FORMAT", ResolveTextureFormat, false },
CommandInfo{ "SOURCE", ResolveTextureSource, false }
};
if (!ResolveBlockCommon(COMMAND_INFOS, source, state, &desc)) {
return false;
}
if (!CheckNextToken<true>(source, state, "Texture2D")) {
return false;
}
std::string_view token;
if (!GetNextToken<true, false>(source, state, token)) {
return false;
}
if (token == "INPUT" || token == "OUTPUT") {
// INPUT 和 OUTPUT 不允许有属性
if (!desc.widthExpr.empty() || !desc.heightExpr.empty() ||
desc.format != ShaderEffectTextureFormat::UNKNOWN || !desc.source.empty())
{
state.errorMsg = "INPUT 和 OUTPUT 不允许有属性";
return false;
}
} else {
desc.name = token;
if (desc.source.empty()) {
// 不存在 SOURCE 属性时必须指定 WIDTH、HEIGHT 和 FORMAT
if (desc.widthExpr.empty()) {
state.errorMsg = "缺少 WIDTH 属性";
return false;
}
if (isMetaIdicator) {
std::string_view tempSource = sourceView.substr(i + 3);
std::string_view token;
if (!GetNextToken<false, false>(tempSource, state, token)) {
return false;
}
if (desc.heightExpr.empty()) {
state.errorMsg = "缺少 HEIGHT 属性";
return false;
}
std::string newBlockType = StrHelper::ToUpperCase(token);
size_t newBlockOffset = tempSource.data() - sourceView.data();
if (desc.format == ShaderEffectTextureFormat::UNKNOWN) {
state.errorMsg = "缺少 FORMAT 属性";
return false;
}
} else {
// SOURCE 和 WIDTH/HEIGHT 冲突
if (!desc.widthExpr.empty() || !desc.heightExpr.empty()) {
state.errorMsg = "SOURCE 和 WIDTH/HEIGHT 冲突";
return false;
}
// sourceView[i - 1] 是换行符,因此每个区块都以换行结尾。区块开头不包含声明该区块的
// 指令,如果该指令没有参数,此区块就以换行符开头。
if (newBlockType == "PARAMETER") {
completeCurrentBlock(BlockType::Parameter, i, newBlockOffset);
} else if (newBlockType == "TEXTURE") {
completeCurrentBlock(BlockType::Texture, i, newBlockOffset);
} else if (newBlockType == "SAMPLER") {
completeCurrentBlock(BlockType::Sampler, i, newBlockOffset);
} else if (newBlockType == "COMMON") {
completeCurrentBlock(BlockType::Common, i, newBlockOffset);
} else if (newBlockType == "PASS") {
completeCurrentBlock(BlockType::Pass, i, newBlockOffset);
}
// 下个循环会加一
i = newBlockOffset - 1;
state.isNewLine = false;
// 存在 SOURCE 时 FORMAT 可选,默认值为 R16G16B16A16_FLOAT
if (desc.format == ShaderEffectTextureFormat::UNKNOWN) {
desc.format = ShaderEffectTextureFormat::R16G16B16A16_FLOAT;
}
}
}
// 结束最后一个区块。sourceView 以换行符结尾,因此最后一个区块也以换行符结尾。
completeCurrentBlock(BlockType::Header, sourceView.size(), std::numeric_limits<size_t>::max());
return true;
if (!RemoveLeadingBlanks(source, state)) {
return false;
}
if (!source.starts_with(';')) {
SetGeneralParseError(state, source, ";");
return false;
}
source.remove_prefix(1);
state.isNewLine = false;
return RequireSourceEnd(source, state);
}
static bool ResolveSamplerFilter(
std::string_view& source,
ParserState& state,
void* data
) noexcept {
std::string_view token;
if (!GetNextToken<false, false>(source, state, token)) {
return false;
}
std::string tokenUpper = StrHelper::ToUpperCase(token);
if (tokenUpper == "LINEAR") {
((ShaderEffectSamplerDesc*)data)->filterType = ShaderEffectSamplerFilterType::Linear;
} else if (tokenUpper == "POINT") {
((ShaderEffectSamplerDesc*)data)->filterType = ShaderEffectSamplerFilterType::Point;
} else {
SetGeneralParseError(state, token, "LINEAR|POINT");
}
return RequireLineEnd(source, state);
}
static bool ResolveSamplerAddress(
std::string_view& source,
ParserState& state,
void* data
) noexcept {
std::string_view token;
if (!GetNextToken<false, false>(source, state, token)) {
return false;
}
std::string tokenUpper = StrHelper::ToUpperCase(token);
if (tokenUpper == "CLAMP") {
((ShaderEffectSamplerDesc*)data)->addressType = ShaderEffectSamplerAddressType::Clamp;
} else if (tokenUpper == "WRAP") {
((ShaderEffectSamplerDesc*)data)->addressType = ShaderEffectSamplerAddressType::Wrap;
} else {
SetGeneralParseError(state, token, "CLAMP|WRAP");
}
return RequireLineEnd(source, state);
}
static bool ResolveSamplerBlock(
std::string_view source,
ParserState& state,
ShaderEffectSamplerDesc& desc
) noexcept {
static constexpr std::array COMMAND_INFOS = {
CommandInfo{ "FILTER", ResolveSamplerFilter, true },
CommandInfo{ "ADDRESS", ResolveSamplerAddress, false },
};
if (!ResolveBlockCommon(COMMAND_INFOS, source, state, &desc)) {
return false;
}
if (!CheckNextToken<true>(source, state, "SamplerState")) {
return false;
}
std::string_view token;
if (!GetNextToken<true, false>(source, state, token)) {
return false;
}
desc.name = token;
if (!RemoveLeadingBlanks(source, state)) {
return false;
}
if (!source.starts_with(';')) {
SetGeneralParseError(state, source, ";");
return false;
}
source.remove_prefix(1);
state.isNewLine = false;
return RequireSourceEnd(source, state);
}
std::string ShaderEffectParser::ParseForInfo(
@ -851,15 +1061,15 @@ std::string ShaderEffectParser::ParseForInfo(
curBlockStartLineNumber = state.lineNumber;
};
if (!ResolveBlocks(sourceView, completeCurrentBlock, state)) {
Logger::Get().Error(StrHelper::Concat("ResolveBlocks 失败\n\t错误消息: ", state.errorMsg));
if (!FindBlocks(sourceView, completeCurrentBlock, state)) {
Logger::Get().Error(StrHelper::Concat("FindBlocks 失败\n\t错误消息: ", state.errorMsg));
return std::move(state.errorMsg);
}
state.lineNumber = headerBlock.startLineNumer;
state.isNewLine = false;
if (!ResolveHeader(headerBlock.source, state, effectInfo)) {
Logger::Get().Error(StrHelper::Concat("ResolveHeader 失败\n\t错误消息: ", state.errorMsg));
if (!ResolveHeaderBlock(headerBlock.source, state, effectInfo)) {
Logger::Get().Error(StrHelper::Concat("ResolveHeaderBlock 失败\n\t错误消息: ", state.errorMsg));
return std::move(state.errorMsg);
}
@ -867,8 +1077,9 @@ std::string ShaderEffectParser::ParseForInfo(
for (size_t i = 0; i < paramBlocks.size(); ++i) {
state.lineNumber = paramBlocks[i].startLineNumer;
state.isNewLine = false;
if (!ResolveParameter(paramBlocks[i].source, state, effectInfo.params[i])) {
Logger::Get().Error(fmt::format("ResolveParameter#{} 失败\n\t错误消息: ", state.errorMsg));
if (!ResolveParameterBlock(paramBlocks[i].source, state, effectInfo.params[i])) {
Logger::Get().Error(fmt::format(
"ResolveParameterBlock#{} 失败\n\t错误消息: {}", i, state.errorMsg));
return std::move(state.errorMsg);
}
}
@ -880,7 +1091,7 @@ std::string ShaderEffectParser::ParseForDesc(
const EffectInfo& /*effectInfo*/,
std::string&& source,
const ShaderEffectParserOptions& /*options*/,
ShaderEffectDesc& /*effectDesc*/,
ShaderEffectDrawInfo& drawInfo,
ShaderEffectSource& /*effectSource*/
) noexcept {
assert(!source.empty());
@ -924,20 +1135,20 @@ std::string ShaderEffectParser::ParseForDesc(
case BlockType::Parameter:
break;
case BlockType::Texture:
textureBlocks.push_back(BlockData{
sourceView.substr(curBlockOffset, curBlockEnd - curBlockOffset),curBlockStartLineNumber });
textureBlocks.push_back(BlockData{ sourceView.substr(
curBlockOffset, curBlockEnd - curBlockOffset),curBlockStartLineNumber });
break;
case BlockType::Sampler:
samplerBlocks.push_back(BlockData{
sourceView.substr(curBlockOffset, curBlockEnd - curBlockOffset),curBlockStartLineNumber });
samplerBlocks.push_back(BlockData{ sourceView.substr(
curBlockOffset, curBlockEnd - curBlockOffset),curBlockStartLineNumber });
break;
case BlockType::Common:
commonBlocks.push_back(BlockData{
sourceView.substr(curBlockOffset, curBlockEnd - curBlockOffset),curBlockStartLineNumber });
commonBlocks.push_back(BlockData{ sourceView.substr(
curBlockOffset, curBlockEnd - curBlockOffset),curBlockStartLineNumber });
break;
case BlockType::Pass:
passBlocks.push_back(BlockData{
sourceView.substr(curBlockOffset, curBlockEnd - curBlockOffset),curBlockStartLineNumber });
passBlocks.push_back(BlockData{ sourceView.substr(
curBlockOffset, curBlockEnd - curBlockOffset),curBlockStartLineNumber });
break;
default:
assert(false);
@ -949,11 +1160,45 @@ std::string ShaderEffectParser::ParseForDesc(
curBlockStartLineNumber = state.lineNumber;
};
if (!ResolveBlocks(sourceView, completeCurrentBlock, state)) {
Logger::Get().Error(StrHelper::Concat("ResolveBlocks 失败\n\t错误消息: ", state.errorMsg));
if (!FindBlocks(sourceView, completeCurrentBlock, state)) {
Logger::Get().Error(StrHelper::Concat("FindBlocks 失败\n\t错误消息: ", state.errorMsg));
return std::move(state.errorMsg);
}
if (passBlocks.empty()) {
state.errorMsg = "未找到 PASS 块";
return std::move(state.errorMsg);
}
for (size_t i = 0; i < textureBlocks.size(); ++i) {
state.lineNumber = textureBlocks[i].startLineNumer;
state.isNewLine = false;
ShaderEffectTextureDesc desc;
if (!ResolveTextureBlock(textureBlocks[i].source, state, desc)) {
Logger::Get().Error(fmt::format(
"ResolveTextureBlock#{} 失败\n\t错误消息: {}", i, state.errorMsg));
return std::move(state.errorMsg);
}
// 排除 INPUT 和 OUTPUT
if (!desc.name.empty()) {
drawInfo.textures.push_back(std::move(desc));
}
}
drawInfo.samplers.resize(samplerBlocks.size());
for (size_t i = 0; i < samplerBlocks.size(); ++i) {
state.lineNumber = samplerBlocks[i].startLineNumer;
state.isNewLine = false;
if (!ResolveSamplerBlock(samplerBlocks[i].source, state, drawInfo.samplers[i])) {
Logger::Get().Error(fmt::format(
"ResolveSamplerBlock#{} 失败\n\t错误消息: {}", i, state.errorMsg));
return std::move(state.errorMsg);
}
}
return std::move(state.errorMsg);
}

View file

@ -4,7 +4,7 @@
namespace Magpie {
struct EffectInfo;
struct ShaderEffectDesc;
struct ShaderEffectDrawInfo;
enum class ShaderEffectParserFlags {
None = 0,
@ -38,7 +38,7 @@ struct ShaderEffectParser {
const EffectInfo& effectInfo,
std::string&& source,
const ShaderEffectParserOptions& options,
ShaderEffectDesc& effectDesc,
ShaderEffectDrawInfo& drawInfo,
ShaderEffectSource& effectSource
) noexcept;
};

View file

@ -1,6 +1,6 @@
#pragma once
#include "EffectInfo.h"
#include "../ShaderEffectDesc.h"
#include "../ShaderEffectDrawInfo.h"
#include <parallel_hashmap/phmap.h>
namespace Magpie {
@ -31,7 +31,7 @@ public:
bool isAdvancedColorSupported
) noexcept;
bool GetTaskResult(std::string taskKey, const ShaderEffectDesc* &effectDesc) noexcept;
bool GetTaskResult(std::string taskKey, const ShaderEffectDrawInfo** effectDesc) noexcept;
// 缩放结束时调用
void CleanCache(bool clearAll) noexcept;
@ -45,7 +45,7 @@ private:
phmap::flat_hash_map<std::string_view, uint32_t> _effectsMap;
struct _ShaderEffectMemCacheItem {
ShaderEffectDesc effectDesc;
ShaderEffectDrawInfo effectDesc;
// UINT_MAX 表示尚未编译完成
uint32_t lastAccess = std::numeric_limits<uint32_t>::max();
};