mirror of
https://github.com/Blinue/Magpie.git
synced 2026-06-24 02:04:10 +00:00
feat: 新版 FX 解析器 (p1)
This commit is contained in:
parent
1cd65609fd
commit
9ac3c6d11d
14 changed files with 228 additions and 348 deletions
|
|
@ -1,75 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "BackendDescriptorStore.h"
|
||||
#include "Logger.h"
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
ID3D11ShaderResourceView* BackendDescriptorStore::GetShaderResourceView(ID3D11Texture2D* texture) noexcept {
|
||||
if (auto it = _srvMap.find(texture); it != _srvMap.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID3D11ShaderResourceView> srv;
|
||||
HRESULT hr = _d3dDevice->CreateShaderResourceView(texture, nullptr, srv.put());
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("CreateShaderResourceView 失败", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _srvMap.emplace(texture, std::move(srv)).first->second.get();
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView* BackendDescriptorStore::GetUnorderedAccessView(ID3D11Texture2D* texture) noexcept {
|
||||
if (auto it = _uavMap.find(texture); it != _uavMap.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID3D11UnorderedAccessView> uav;
|
||||
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC desc{
|
||||
.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D
|
||||
};
|
||||
|
||||
HRESULT hr = _d3dDevice->CreateUnorderedAccessView(texture, &desc, uav.put());
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("CreateUnorderedAccessView 失败", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _uavMap.emplace(texture, std::move(uav)).first->second.get();
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView* BackendDescriptorStore::GetUnorderedAccessView(
|
||||
ID3D11Buffer* buffer,
|
||||
uint32_t numElements,
|
||||
DXGI_FORMAT format
|
||||
) noexcept {
|
||||
if (auto it = _uavMap.find(buffer); it != _uavMap.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID3D11UnorderedAccessView> uav;
|
||||
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC desc{
|
||||
.Format = format,
|
||||
.ViewDimension = D3D11_UAV_DIMENSION_BUFFER,
|
||||
.Buffer{
|
||||
.NumElements = numElements
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT hr = _d3dDevice->CreateUnorderedAccessView(buffer, &desc, uav.put());
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("CreateUnorderedAccessView 失败", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _uavMap.emplace(buffer, std::move(uav)).first->second.get();
|
||||
}
|
||||
|
||||
void BackendDescriptorStore::RemoveCache(ID3D11Texture2D* texture) noexcept {
|
||||
_srvMap.erase(texture);
|
||||
_uavMap.erase(texture);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#pragma once
|
||||
#include <parallel_hashmap/phmap.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
class BackendDescriptorStore {
|
||||
public:
|
||||
BackendDescriptorStore() = default;
|
||||
BackendDescriptorStore(const BackendDescriptorStore&) = delete;
|
||||
BackendDescriptorStore(BackendDescriptorStore&&) = default;
|
||||
|
||||
void Initialize(ID3D11Device5* d3dDevice) noexcept {
|
||||
_d3dDevice = d3dDevice;
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView* GetShaderResourceView(ID3D11Texture2D* texture) noexcept;
|
||||
|
||||
ID3D11UnorderedAccessView* GetUnorderedAccessView(ID3D11Texture2D* texture) noexcept;
|
||||
|
||||
ID3D11UnorderedAccessView* GetUnorderedAccessView(
|
||||
ID3D11Buffer* buffer,
|
||||
uint32_t numElements,
|
||||
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN
|
||||
) noexcept;
|
||||
|
||||
void RemoveCache(ID3D11Texture2D* texture) noexcept;
|
||||
|
||||
private:
|
||||
ID3D11Device5* _d3dDevice = nullptr;
|
||||
|
||||
phmap::flat_hash_map<ID3D11Texture2D*, winrt::com_ptr<ID3D11ShaderResourceView>> _srvMap;
|
||||
phmap::flat_hash_map<void*, winrt::com_ptr<ID3D11UnorderedAccessView>> _uavMap;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "SmallVector.h"
|
||||
#include <d3d11_4.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,124 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "EffectsProfiler.h"
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
void EffectsProfiler::Start(ID3D11Device* d3dDevice, uint32_t passCount) noexcept {
|
||||
assert(!IsProfiling() && passCount > 0);
|
||||
|
||||
_passQueries.resize(passCount);
|
||||
|
||||
D3D11_QUERY_DESC desc{ .Query = D3D11_QUERY_TIMESTAMP_DISJOINT };
|
||||
d3dDevice->CreateQuery(&desc, _disjointQuery.put());
|
||||
|
||||
desc.Query = D3D11_QUERY_TIMESTAMP;
|
||||
d3dDevice->CreateQuery(&desc, _startQuery.put());
|
||||
for (winrt::com_ptr<ID3D11Query>& query : _passQueries) {
|
||||
d3dDevice->CreateQuery(&desc, query.put());
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsProfiler::Stop() noexcept {
|
||||
_disjointQuery = nullptr;
|
||||
_startQuery = nullptr;
|
||||
_passQueries.clear();
|
||||
}
|
||||
|
||||
bool EffectsProfiler::IsProfiling() const noexcept {
|
||||
return (bool)_disjointQuery;
|
||||
}
|
||||
|
||||
void EffectsProfiler::SetPassCount(ID3D11Device* d3dDevice, uint32_t passCount) noexcept {
|
||||
if (!IsProfiling()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(passCount > 0);
|
||||
const uint32_t oldPassCount = (uint32_t)_passQueries.size();
|
||||
|
||||
if (passCount == oldPassCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
_passQueries.resize(passCount);
|
||||
|
||||
if (passCount > oldPassCount) {
|
||||
D3D11_QUERY_DESC desc{ .Query = D3D11_QUERY_TIMESTAMP };
|
||||
for (uint32_t i = oldPassCount; i < passCount; ++i) {
|
||||
d3dDevice->CreateQuery(&desc, _passQueries[i].put());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsProfiler::OnBeginEffects(ID3D11DeviceContext* d3dDC) noexcept {
|
||||
if (!IsProfiling()) {
|
||||
return;
|
||||
}
|
||||
|
||||
d3dDC->Begin(_disjointQuery.get());
|
||||
d3dDC->End(_startQuery.get());
|
||||
|
||||
_curPass = 0;
|
||||
}
|
||||
|
||||
void EffectsProfiler::OnEndPass(ID3D11DeviceContext* d3dDC) noexcept {
|
||||
if (!IsProfiling()) {
|
||||
return;
|
||||
}
|
||||
|
||||
d3dDC->End(_passQueries[_curPass++].get());
|
||||
}
|
||||
|
||||
void EffectsProfiler::OnEndEffects(ID3D11DeviceContext* d3dDC) noexcept {
|
||||
if (!IsProfiling()) {
|
||||
return;
|
||||
}
|
||||
|
||||
d3dDC->End(_disjointQuery.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T GetQueryData(ID3D11DeviceContext* d3dDC, ID3D11Query* query) noexcept {
|
||||
T data{};
|
||||
while (d3dDC->GetData(query, &data, sizeof(data), 0) != S_OK) {
|
||||
Sleep(0);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void EffectsProfiler::QueryTimings(ID3D11DeviceContext* d3dDC) noexcept {
|
||||
if (!IsProfiling()) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData =
|
||||
GetQueryData<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT>(d3dDC, _disjointQuery.get());
|
||||
|
||||
if (disjointData.Disjoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float toMS = 1000.0f / disjointData.Frequency;
|
||||
|
||||
uint64_t prevTimestamp = GetQueryData<uint64_t>(d3dDC, _startQuery.get());
|
||||
|
||||
auto lock = _timingsLock.lock_exclusive();
|
||||
_timings.resize(_passQueries.size());
|
||||
for (size_t i = 0; i < _passQueries.size(); ++i) {
|
||||
uint64_t timestamp = GetQueryData<uint64_t>(d3dDC, _passQueries[i].get());
|
||||
_timings[i] = (timestamp - prevTimestamp) * toMS;
|
||||
|
||||
prevTimestamp = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
SmallVector<float> EffectsProfiler::GetTimings() noexcept {
|
||||
auto lock = _timingsLock.lock_exclusive();
|
||||
|
||||
// 没有渲染新帧时 _timings 为空
|
||||
SmallVector<float> result = std::move(_timings);
|
||||
_timings.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
#pragma once
|
||||
#include "SmallVector.h"
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
class DeviceResources;
|
||||
|
||||
class EffectsProfiler {
|
||||
public:
|
||||
EffectsProfiler() = default;
|
||||
|
||||
EffectsProfiler(const EffectsProfiler&) = delete;
|
||||
EffectsProfiler(EffectsProfiler&&) = delete;
|
||||
|
||||
void Start(ID3D11Device* d3dDevice, uint32_t passCount) noexcept;
|
||||
|
||||
void Stop() noexcept;
|
||||
|
||||
bool IsProfiling() const noexcept;
|
||||
|
||||
void SetPassCount(ID3D11Device* d3dDevice, uint32_t passCount) noexcept;
|
||||
|
||||
void OnBeginEffects(ID3D11DeviceContext* d3dDC) noexcept;
|
||||
|
||||
void OnEndPass(ID3D11DeviceContext* d3dDC) noexcept;
|
||||
|
||||
void OnEndEffects(ID3D11DeviceContext* d3dDC) noexcept;
|
||||
|
||||
void QueryTimings(ID3D11DeviceContext* d3dDC) noexcept;
|
||||
|
||||
// 从前端线程调用
|
||||
SmallVector<float> GetTimings() noexcept;
|
||||
|
||||
private:
|
||||
SmallVector<float> _timings;
|
||||
wil::srwlock _timingsLock;
|
||||
|
||||
winrt::com_ptr<ID3D11Query> _disjointQuery;
|
||||
winrt::com_ptr<ID3D11Query> _startQuery;
|
||||
std::vector<winrt::com_ptr<ID3D11Query>> _passQueries;
|
||||
|
||||
uint32_t _curPass = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "SmallVector.h"
|
||||
#include <d3d11_4.h>
|
||||
#include <ShlObj.h>
|
||||
#include <winrt/Windows.Graphics.Capture.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@
|
|||
</FxCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BackendDescriptorStore.h" />
|
||||
<ClInclude Include="CatmullRomDrawer.h" />
|
||||
<ClInclude Include="ColorHelper.h" />
|
||||
<ClInclude Include="CommandContext.h" />
|
||||
|
|
@ -63,7 +62,6 @@
|
|||
<ClInclude Include="EffectDrawerBase.h" />
|
||||
<ClInclude Include="EffectHelper.h" />
|
||||
<ClInclude Include="EffectsDrawer.h" />
|
||||
<ClInclude Include="EffectsProfiler.h" />
|
||||
<ClInclude Include="ExclModeHelper.h" />
|
||||
<ClInclude Include="FrameProducer.h" />
|
||||
<ClInclude Include="CursorHelper.h" />
|
||||
|
|
@ -93,7 +91,6 @@
|
|||
<ClInclude Include="SwapChainPresenter.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BackendDescriptorStore.cpp" />
|
||||
<ClCompile Include="CatmullRomDrawer.cpp" />
|
||||
<ClCompile Include="CommandContext.cpp" />
|
||||
<ClCompile Include="CursorDrawer.cpp" />
|
||||
|
|
@ -104,7 +101,6 @@
|
|||
<ClCompile Include="DescriptorHeap.cpp" />
|
||||
<ClCompile Include="EffectCompiler.cpp" />
|
||||
<ClCompile Include="EffectsDrawer.cpp" />
|
||||
<ClCompile Include="EffectsProfiler.cpp" />
|
||||
<ClCompile Include="ExclModeHelper.cpp" />
|
||||
<ClCompile Include="FrameProducer.cpp" />
|
||||
<ClCompile Include="CursorHelper.cpp" />
|
||||
|
|
|
|||
|
|
@ -60,9 +60,6 @@
|
|||
<ClInclude Include="include\DirectXHelper.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BackendDescriptorStore.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CursorDrawer.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -72,16 +69,10 @@
|
|||
<ClInclude Include="StepTimer.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EffectsProfiler.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DDS.h">
|
||||
<Filter>Helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SrcTracker.h" />
|
||||
<ClInclude Include="Renderer2.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SwapChainPresenter.h">
|
||||
<Filter>Presenter</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -140,6 +131,7 @@
|
|||
<ClInclude Include="CommandContext.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Renderer.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ScalingRuntime.cpp" />
|
||||
|
|
@ -157,9 +149,6 @@
|
|||
<ClCompile Include="Win32Helper.cpp">
|
||||
<Filter>Helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BackendDescriptorStore.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CursorDrawer.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -169,13 +158,7 @@
|
|||
<ClCompile Include="StepTimer.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EffectsProfiler.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SrcTracker.cpp" />
|
||||
<ClCompile Include="Renderer2.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SwapChainPresenter.cpp">
|
||||
<Filter>Presenter</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -219,6 +202,7 @@
|
|||
<ClCompile Include="CommandContext.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Renderer.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FxCompile Include="shaders\MaskedCursorPS.hlsl">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#include "pch.h"
|
||||
#include "ShaderEffectParser.h"
|
||||
#include "EffectInfo.h"
|
||||
#include "Win32Helper.h"
|
||||
#include "StrHelper.h"
|
||||
#include "Logger.h"
|
||||
#include "ShaderEffectDesc.h"
|
||||
|
||||
namespace Magpie {
|
||||
|
|
@ -9,61 +10,233 @@ namespace Magpie {
|
|||
// 当前 MagpieFX 版本
|
||||
// static constexpr uint32_t MAGPIE_FX_VERSION = 4;
|
||||
|
||||
// static const char* META_INDICATOR = "//!";
|
||||
// 必须出现在一行的开头才视为指令
|
||||
static const char* META_INDICATOR = "//!";
|
||||
|
||||
class PassInclude : public ID3DInclude {
|
||||
public:
|
||||
PassInclude(std::wstring_view localDir) : _localDir(localDir) {}
|
||||
|
||||
PassInclude(const PassInclude&) = default;
|
||||
PassInclude(PassInclude&&) = default;
|
||||
|
||||
HRESULT CALLBACK Open(
|
||||
D3D_INCLUDE_TYPE /*IncludeType*/,
|
||||
LPCSTR pFileName,
|
||||
LPCVOID /*pParentData*/,
|
||||
LPCVOID* ppData,
|
||||
UINT* pBytes
|
||||
) noexcept override {
|
||||
std::wstring relativePath = StrHelper::Concat(_localDir, StrHelper::UTF8ToUTF16(pFileName));
|
||||
|
||||
std::string content;
|
||||
if (!Win32Helper::ReadTextFile(relativePath.c_str(), content)) {
|
||||
Logger::Get().Win32Error("Win32Helper::ReadTextFile 失败");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> data = std::make_unique<char[]>(content.size());
|
||||
std::memcpy(data.get(), content.data(), content.size());
|
||||
|
||||
*ppData = data.release();
|
||||
*pBytes = (UINT)content.size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CALLBACK Close(LPCVOID pData) noexcept override {
|
||||
std::unique_ptr<char[]>((char*)pData).reset();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
std::wstring _localDir;
|
||||
struct ParserState {
|
||||
std::string errorMsg;
|
||||
uint32_t lineNumber;
|
||||
bool isNewLine;
|
||||
};
|
||||
|
||||
bool ShaderEffectParser::ParseForInfo(std::string&& name, std::string&& /*source*/, EffectInfo& effectInfo) noexcept {
|
||||
static void RemoveLeadingSpaces(std::string_view& source, ParserState& state) noexcept {
|
||||
size_t i = 0;
|
||||
for (; i < source.size(); ++i) {
|
||||
if (source[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
source.remove_prefix(i);
|
||||
state.isNewLine = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RemoveLeadingBlanks(std::string_view& source, ParserState& state) noexcept {
|
||||
size_t i = 0;
|
||||
for (; i < source.size(); ++i) {
|
||||
char c = source[i];
|
||||
|
||||
if (c == ' ' || c == '\t') {
|
||||
state.isNewLine = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\n') {
|
||||
++state.lineNumber;
|
||||
state.isNewLine = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '/') {
|
||||
// source 以换行符结尾,因此可以安全提取非换行符的下一个的字符
|
||||
char nextChar = source[i + 1];
|
||||
|
||||
if (nextChar == '/') {
|
||||
if (!state.isNewLine || source[i + 2] != '!') {
|
||||
// 行注释而非指令
|
||||
i += 2;
|
||||
while (source[i] != '\n') {
|
||||
++i;
|
||||
}
|
||||
|
||||
++state.lineNumber;
|
||||
state.isNewLine = true;
|
||||
continue;
|
||||
}
|
||||
} else if (nextChar == '*') {
|
||||
// 块注释
|
||||
i += 2;
|
||||
|
||||
while (true) {
|
||||
c = source[i];
|
||||
|
||||
if (c == '*') {
|
||||
if (source[i + 1] == '/') {
|
||||
// 块注释结束
|
||||
++i;
|
||||
state.isNewLine = false;
|
||||
break;
|
||||
}
|
||||
} else if (c == '\n') {
|
||||
// 块注释中换行不记为新行
|
||||
++state.lineNumber;
|
||||
|
||||
// 提取换行符的后一个字符需检查文件结尾
|
||||
if (i + 1 == source.size()) {
|
||||
state.errorMsg = "块注释未闭合";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
source.remove_prefix(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <bool SkipBlanks>
|
||||
static bool GetNextToken(std::string_view& source, ParserState& state, std::string_view& result) noexcept {
|
||||
if (SkipBlanks) {
|
||||
if (!RemoveLeadingBlanks(source, state)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
RemoveLeadingSpaces(source, state);
|
||||
}
|
||||
|
||||
if (source.empty()) {
|
||||
result = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
char c = source[0];
|
||||
|
||||
// 必须以字母或下划线开头
|
||||
if (!StrHelper::isalpha(c) && c != '_') {
|
||||
state.errorMsg = fmt::format("Unexpected character \"{}\" in line {}.", c, state.lineNumber);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 可以包含字母、数字或下划线
|
||||
size_t i = 1;
|
||||
for (; i < source.size(); ++i) {
|
||||
c = source[i];
|
||||
|
||||
if (!StrHelper::isalnum(c) && c != '_') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = source.substr(0, i);
|
||||
source.remove_prefix(i);
|
||||
state.isNewLine = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <bool SkipBlanks>
|
||||
static bool CheckNextToken(std::string_view& source, ParserState& state, std::string_view expectedToken) noexcept {
|
||||
std::string_view token;
|
||||
if (!GetNextToken<SkipBlanks>(source, state, token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token == expectedToken) {
|
||||
return true;
|
||||
} else {
|
||||
state.errorMsg = fmt::format("Unexpected token \"{}\" in line {}.", token, state.lineNumber);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckMetaIndicator(std::string_view& source, ParserState& state) noexcept {
|
||||
if (!RemoveLeadingBlanks(source, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state.isNewLine && source.starts_with(META_INDICATOR)) {
|
||||
source.remove_prefix(StrHelper::StrLen(META_INDICATOR));
|
||||
state.isNewLine = false;
|
||||
return true;
|
||||
} else {
|
||||
state.errorMsg = fmt::format("Unexpected character \"{}\" in line {}.", source[0], state.lineNumber);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckLineEnd(std::string_view& source, ParserState& state) noexcept {
|
||||
RemoveLeadingSpaces(source, state);
|
||||
|
||||
if (source.empty() || source[0] == '\n') {
|
||||
return true;
|
||||
} else {
|
||||
state.errorMsg = fmt::format("Unexpected character \"{}\" in line {}.", source[0], state.lineNumber);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckMagic(std::string_view& source, ParserState& state) noexcept {
|
||||
if (!CheckMetaIndicator(source, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckNextToken<false>(source, state, "MAGPIE")) {
|
||||
return false;
|
||||
}
|
||||
if (!CheckNextToken<false>(source, state, "EFFECT")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CheckLineEnd(source, state);
|
||||
}
|
||||
|
||||
std::string ShaderEffectParser::ParseForInfo(
|
||||
std::string&& name,
|
||||
std::string&& source,
|
||||
EffectInfo2& effectInfo
|
||||
) noexcept {
|
||||
assert(!name.empty() && !source.empty());
|
||||
|
||||
effectInfo.name = std::move(name);
|
||||
|
||||
return false;
|
||||
ParserState state = {
|
||||
.lineNumber = 1,
|
||||
.isNewLine = true
|
||||
};
|
||||
|
||||
// 确保源代码以换行结尾,这可以有效简化文件结尾检查
|
||||
if (!source.ends_with('\n')) {
|
||||
source.push_back('\n');
|
||||
}
|
||||
std::string_view sourceView(source);
|
||||
|
||||
if (!CheckMagic(sourceView, state)) {
|
||||
Logger::Get().Error("检查 MagpieFX 头失败");
|
||||
return std::move(state.errorMsg);
|
||||
}
|
||||
|
||||
return std::move(state.errorMsg);
|
||||
}
|
||||
|
||||
bool ShaderEffectParser::ParseForDesc(
|
||||
std::string&& name,
|
||||
std::string&& /*source*/,
|
||||
std::string_view source,
|
||||
std::string&& workingFolder,
|
||||
const ShaderEffectParserOptions& /*options*/,
|
||||
struct ShaderEffectDesc& effectDesc,
|
||||
ShaderEffectSource& effectSource
|
||||
) noexcept {
|
||||
assert(!name.empty() && !source.empty() && !workingFolder.empty());
|
||||
|
||||
effectDesc.name = std::move(name);
|
||||
effectSource.workingFolder = std::move(workingFolder);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -12,23 +12,20 @@ struct EffectInfoParameter {
|
|||
float step;
|
||||
};
|
||||
|
||||
enum class EffectInfoFlags {
|
||||
enum class EffectInfoFlags2 {
|
||||
None,
|
||||
SupportFP16 = 1,
|
||||
// 必须支持一个或 linear sRGB + scRGB
|
||||
SupportLinearSRGB = 1 << 1,
|
||||
SupportScRGB = 1 << 2,
|
||||
SupportSRGB = 1 << 3
|
||||
SupportAdvancedColor = 1 << 1,
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(EffectInfoFlags)
|
||||
DEFINE_ENUM_FLAG_OPERATORS(EffectInfoFlags2)
|
||||
|
||||
struct EffectInfo {
|
||||
struct EffectInfo2 {
|
||||
std::string name;
|
||||
std::string sortName;
|
||||
std::vector<EffectInfoParameter> params;
|
||||
// 可使用 INPUT_WIDTH,空字符串表示支持自由缩放
|
||||
std::pair<std::string, std::string> outputSizeExprs;
|
||||
EffectInfoFlags flags = EffectInfoFlags::SupportLinearSRGB;
|
||||
EffectInfoFlags2 flags = EffectInfoFlags2::None;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ enum class ShaderEffectParserFlags {
|
|||
None = 0,
|
||||
// 只在效果支持 FP16 时影响字节码
|
||||
EnableFP16 = 1,
|
||||
// 只在效果同时支持 linear sRGB 和 scRGB 时影响字节码
|
||||
// 只在效果支持 scRGB 时影响字节码
|
||||
EnableAdvancedColor = 1 << 1
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(ShaderEffectParserFlags)
|
||||
|
|
@ -15,7 +15,7 @@ DEFINE_ENUM_FLAG_OPERATORS(ShaderEffectParserFlags)
|
|||
struct ShaderEffectParserOptions {
|
||||
// 只在效果存在参数时影响字节码。为空表示不内联
|
||||
const phmap::flat_hash_map<std::string, float>* inlineParams = nullptr;
|
||||
// 只在效果支持 shader model 时影响字节码
|
||||
// 始终影响字节码
|
||||
D3D_SHADER_MODEL shaderModel = D3D_SHADER_MODEL_5_1;
|
||||
ShaderEffectParserFlags flags = ShaderEffectParserFlags::None;
|
||||
};
|
||||
|
|
@ -29,11 +29,16 @@ struct ShaderEffectSource {
|
|||
};
|
||||
|
||||
struct ShaderEffectParser {
|
||||
static bool ParseForInfo(std::string&& name, std::string&& source, struct EffectInfo& effectInfo) noexcept;
|
||||
// 成功时返回空字符串,否则返回错误消息
|
||||
static std::string ParseForInfo(
|
||||
std::string&& name,
|
||||
std::string&& source,
|
||||
struct EffectInfo2& effectInfo
|
||||
) noexcept;
|
||||
|
||||
static bool ParseForDesc(
|
||||
std::string&& name,
|
||||
std::string&& source,
|
||||
std::string_view source,
|
||||
std::string&& workingFolder,
|
||||
const ShaderEffectParserOptions& options,
|
||||
struct ShaderEffectDesc& effectDesc,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#undef GetCurrentTime
|
||||
|
||||
// DirectX 头文件
|
||||
#include <d3d11_4.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3d12.h>
|
||||
#include <d3dx12.h>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include "Event.h"
|
||||
#include <dxgi1_6.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@
|
|||
#undef GetCurrentTime
|
||||
#undef GetNextSibling
|
||||
|
||||
// DirectX 头文件
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3d12.h>
|
||||
|
||||
// C++ 运行时
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue