mirror of
https://github.com/Blinue/Magpie.git
synced 2026-06-24 02:04:10 +00:00
feat: 新版 FX 解析器 (p4)
This commit is contained in:
parent
a7c3f766f7
commit
0279dca40c
43 changed files with 391 additions and 363 deletions
|
|
@ -21,8 +21,8 @@ void CatmullRomDrawer::Initialize(D3D12Context& d3d12Context) noexcept {
|
|||
|
||||
HRESULT CatmullRomDrawer::Draw(
|
||||
ComputeContext& computeContext,
|
||||
Size inputSize,
|
||||
Size outputSize,
|
||||
SizeU inputSize,
|
||||
SizeU outputSize,
|
||||
uint32_t inputSrvOffset,
|
||||
uint32_t outputUavOffset,
|
||||
bool outputSrgb
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ public:
|
|||
|
||||
HRESULT Draw(
|
||||
ComputeContext& computeContext,
|
||||
Size inputSize,
|
||||
Size outputSize,
|
||||
SizeU inputSize,
|
||||
SizeU outputSize,
|
||||
uint32_t inputSrvOffset,
|
||||
uint32_t outputUavOffset,
|
||||
bool outputSrgb
|
||||
|
|
|
|||
|
|
@ -519,7 +519,7 @@ void CursorDrawer::OnColorInfoChanged(const ColorInfo& colorInfo) noexcept {
|
|||
_ClearCursorInfos();
|
||||
}
|
||||
|
||||
static bool GetCursorSizeFromBmps(HBITMAP hColorBmp, HBITMAP hMaskBmp, Size& size) noexcept {
|
||||
static bool GetCursorSizeFromBmps(HBITMAP hColorBmp, HBITMAP hMaskBmp, SizeU& size) noexcept {
|
||||
BITMAP bmp{};
|
||||
if (!GetObject(hColorBmp ? hColorBmp : hMaskBmp, sizeof(bmp), &bmp)) {
|
||||
Logger::Get().Win32Error("GetObject 失败");
|
||||
|
|
@ -532,7 +532,7 @@ static bool GetCursorSizeFromBmps(HBITMAP hColorBmp, HBITMAP hMaskBmp, Size& siz
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool GetCursorSizeUnderDpi96(HCURSOR hCursor, Size& cursorSize) noexcept {
|
||||
static bool GetCursorSizeUnderDpi96(HCURSOR hCursor, SizeU& cursorSize) noexcept {
|
||||
ICONINFO iconInfo{};
|
||||
{
|
||||
DPI_AWARENESS_CONTEXT oldDpiContext =
|
||||
|
|
@ -596,7 +596,7 @@ std::pair<const CursorDrawer::_CursorInfoKey, CursorDrawer::_CursorInfo>* Cursor
|
|||
wil::unique_hbitmap hResColorBmp(cursorIconInfoEx.hbmColor);
|
||||
wil::unique_hbitmap hResMaskBmp(cursorIconInfoEx.hbmMask);
|
||||
|
||||
Size cursorBmpSize;
|
||||
SizeU cursorBmpSize;
|
||||
if (!GetCursorSizeFromBmps(hResColorBmp.get(), hResMaskBmp.get(), cursorBmpSize)) {
|
||||
Logger::Get().Error("GetCursorSizeFromBmps 失败");
|
||||
return nullptr;
|
||||
|
|
@ -609,7 +609,7 @@ std::pair<const CursorDrawer::_CursorInfoKey, CursorDrawer::_CursorInfo>* Cursor
|
|||
// 如果不能确定光标是否随 DPI 缩放则假设为真,绝大多数时候是对的
|
||||
cursorInfo.size = _CalcCursorSize(cursorBmpSize, SYSTEM_DPI, monitorDpi, true);
|
||||
} else {
|
||||
Size cursorSizeDpi96;
|
||||
SizeU cursorSizeDpi96;
|
||||
if (!GetCursorSizeUnderDpi96(hCursor, cursorSizeDpi96)) {
|
||||
Logger::Get().Error("GetCursorSizeUnderDpi96 失败");
|
||||
return nullptr;
|
||||
|
|
@ -621,7 +621,7 @@ std::pair<const CursorDrawer::_CursorInfoKey, CursorDrawer::_CursorInfo>* Cursor
|
|||
}
|
||||
|
||||
SmallVector<wil::unique_hcursor, 1> cursorFrameRes;
|
||||
Point resHotspot = { cursorIconInfoEx.xHotspot, cursorIconInfoEx.yHotspot };
|
||||
PointU resHotspot = { cursorIconInfoEx.xHotspot, cursorIconInfoEx.yHotspot };
|
||||
|
||||
// 尝试从光标原始来源加载指定尺寸的资源,如果失败旧只能使用 GetIconInfo 得到的位图,
|
||||
// DPI 虚拟化机制可能导致图像质量严重下降。
|
||||
|
|
@ -700,8 +700,8 @@ std::pair<const CursorDrawer::_CursorInfoKey, CursorDrawer::_CursorInfo>* Cursor
|
|||
std::move(cursorInfo)).first;
|
||||
}
|
||||
|
||||
Size CursorDrawer::_CalcCursorSize(
|
||||
Size cursorBmpSize,
|
||||
SizeU CursorDrawer::_CalcCursorSize(
|
||||
SizeU cursorBmpSize,
|
||||
uint32_t cursorDpi,
|
||||
uint32_t monitorDpi,
|
||||
bool isCursorDpiAware
|
||||
|
|
@ -826,7 +826,7 @@ bool CursorDrawer::_ResolveCursorFramePixels(
|
|||
HBITMAP hColorBmp,
|
||||
HBITMAP hMaskBmp
|
||||
) const noexcept {
|
||||
const Size bmpSize = {
|
||||
const SizeU bmpSize = {
|
||||
cursorFrame.resSize.width,
|
||||
hColorBmp ? cursorFrame.resSize.height : cursorFrame.resSize.height * 2
|
||||
};
|
||||
|
|
|
|||
|
|
@ -103,10 +103,10 @@ private:
|
|||
|
||||
struct _CursorFrame {
|
||||
_CursorType type;
|
||||
Point hotspot;
|
||||
PointU hotspot;
|
||||
|
||||
winrt::com_ptr<ID3D12Resource> texture;
|
||||
Size resSize;
|
||||
SizeU resSize;
|
||||
ByteBuffer resTextureData;
|
||||
// 这两个资源使用完毕后在 _ClearRetiredResources 中释放
|
||||
winrt::com_ptr<ID3D12Resource> uploadBuffer;
|
||||
|
|
@ -119,7 +119,7 @@ private:
|
|||
};
|
||||
|
||||
struct _CursorInfo {
|
||||
Size size;
|
||||
SizeU size;
|
||||
SmallVector<_CursorFrame, 1> frames;
|
||||
// 序列表 (帧索引值数组),使多帧可以复用同一个 _CursorFrame。为空表示顺序播放
|
||||
SmallVector<std::pair<uint32_t, std::chrono::nanoseconds>, 0> frameSequence;
|
||||
|
|
@ -144,8 +144,8 @@ private:
|
|||
POINT cursorPos
|
||||
) noexcept;
|
||||
|
||||
Size _CalcCursorSize(
|
||||
Size cursorBmpSize,
|
||||
SizeU _CalcCursorSize(
|
||||
SizeU cursorBmpSize,
|
||||
uint32_t cursorDpi,
|
||||
uint32_t monitorDpi,
|
||||
bool isCursorDpiAware
|
||||
|
|
@ -190,7 +190,7 @@ private:
|
|||
void _OnCursorsRegChanged(wil::RegistryChangeKind) noexcept;
|
||||
|
||||
D3D12Context* _d3d12Context = nullptr;
|
||||
Size _srcSize{};
|
||||
SizeU _srcSize{};
|
||||
RECT _rendererRect{};
|
||||
RECT _destRect{};
|
||||
ColorInfo _colorInfo;
|
||||
|
|
@ -222,7 +222,7 @@ private:
|
|||
|
||||
// 用于从渲染目标复制光标下区域
|
||||
winrt::com_ptr<ID3D12Resource> _tempOriginTexture;
|
||||
Size _tempOriginTextureSize{};
|
||||
SizeU _tempOriginTextureSize{};
|
||||
uint32_t _tempOriginTextureSrvOffset = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
struct _RetiredTempOriginTexture {
|
||||
|
|
|
|||
|
|
@ -5,20 +5,20 @@
|
|||
|
||||
namespace Magpie {
|
||||
|
||||
static bool IsCornerInRect(Point p, const Rect& r) noexcept {
|
||||
static bool IsCornerInRect(PointU p, const RectU& r) noexcept {
|
||||
return p.x >= r.left && p.x <= r.right && p.y >= r.top && p.y <= r.bottom;
|
||||
}
|
||||
|
||||
static bool OptimizeDirtyRectPair(Rect& rect1, Rect& rect2, bool reversed = false) noexcept {
|
||||
static bool OptimizeDirtyRectPair(RectU& rect1, RectU& rect2, bool reversed = false) noexcept {
|
||||
if (RectHelper::IsEmpty(rect1) || RectHelper::IsEmpty(rect2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 计算 rect2 有几个角在 rect1 内
|
||||
bool lt = IsCornerInRect(Point{ rect2.left, rect2.top }, rect1);
|
||||
bool rt = IsCornerInRect(Point{ rect2.right, rect2.top }, rect1);
|
||||
bool rb = IsCornerInRect(Point{ rect2.right, rect2.bottom }, rect1);
|
||||
bool lb = IsCornerInRect(Point{ rect2.left, rect2.bottom }, rect1);
|
||||
bool lt = IsCornerInRect(PointU{ rect2.left, rect2.top }, rect1);
|
||||
bool rt = IsCornerInRect(PointU{ rect2.right, rect2.top }, rect1);
|
||||
bool rb = IsCornerInRect(PointU{ rect2.right, rect2.bottom }, rect1);
|
||||
bool lb = IsCornerInRect(PointU{ rect2.left, rect2.bottom }, rect1);
|
||||
uint32_t count = (uint32_t)lt + (uint32_t)rt + (uint32_t)rb + (uint32_t)lb;
|
||||
|
||||
if (count <= 1) {
|
||||
|
|
@ -124,7 +124,7 @@ static bool OptimizeDirtyRectPair(Rect& rect1, Rect& rect2, bool reversed = fals
|
|||
return false;
|
||||
}
|
||||
|
||||
static void BasicOptimize(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
||||
static void BasicOptimize(SmallVectorImpl<RectU>& dirtyRects) noexcept {
|
||||
// 持续循环直到不再能优化
|
||||
while (true) {
|
||||
const uint32_t count = (uint32_t)dirtyRects.size();
|
||||
|
|
@ -145,7 +145,7 @@ static void BasicOptimize(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
|||
|
||||
// 从后向前删除空矩形
|
||||
for (int i = int(count - 1); i >= 0; --i) {
|
||||
const Rect& rect = dirtyRects[i];
|
||||
const RectU& rect = dirtyRects[i];
|
||||
if (RectHelper::IsEmpty(rect)) {
|
||||
dirtyRects.erase(dirtyRects.begin() + i);
|
||||
}
|
||||
|
|
@ -153,9 +153,9 @@ static void BasicOptimize(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t CalcTotalPixels(const SmallVectorImpl<Rect>& rects) noexcept {
|
||||
static uint32_t CalcTotalPixels(const SmallVectorImpl<RectU>& rects) noexcept {
|
||||
uint32_t result = 0;
|
||||
for (const Rect& rect : rects) {
|
||||
for (const RectU& rect : rects) {
|
||||
result += RectHelper::CalcArea(rect);
|
||||
}
|
||||
return result;
|
||||
|
|
@ -163,16 +163,19 @@ static uint32_t CalcTotalPixels(const SmallVectorImpl<Rect>& rects) noexcept {
|
|||
|
||||
#ifdef MP_DEBUG_INFO
|
||||
// 验证优化算法的正确性
|
||||
static void ValidateOptimize(const SmallVectorImpl<Rect>& originRects, const SmallVectorImpl<Rect>& newRects) noexcept {
|
||||
static void ValidateOptimize(
|
||||
const SmallVectorImpl<RectU>& originRects,
|
||||
const SmallVectorImpl<RectU>& newRects
|
||||
) noexcept {
|
||||
if (originRects.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<bool> pixels;
|
||||
for (const Rect& originRect : originRects) {
|
||||
for (const RectU& originRect : originRects) {
|
||||
// 作为优化先检查有没有被优化后的某个矩形包含
|
||||
bool contained = false;
|
||||
for (const Rect& newRect : newRects) {
|
||||
for (const RectU& newRect : newRects) {
|
||||
if (RectHelper::Contains(newRect, originRect)) {
|
||||
contained = true;
|
||||
break;
|
||||
|
|
@ -186,7 +189,7 @@ static void ValidateOptimize(const SmallVectorImpl<Rect>& originRects, const Sma
|
|||
const uint32_t originWidth = originRect.right - originRect.left;
|
||||
pixels.assign(size_t((originRect.bottom - originRect.top) * originWidth), false);
|
||||
|
||||
for (Rect newRect : newRects) {
|
||||
for (RectU newRect : newRects) {
|
||||
if (!RectHelper::Intersect(newRect, newRect, originRect)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -201,7 +204,7 @@ static void ValidateOptimize(const SmallVectorImpl<Rect>& originRects, const Sma
|
|||
if (std::find(pixels.begin(), pixels.end(), false) != pixels.end()) {
|
||||
OutputDebugString(L"优化脏矩形算法错误!\n");
|
||||
// 打印脏矩形供调试
|
||||
for (const Rect& rect : originRects) {
|
||||
for (const RectU& rect : originRects) {
|
||||
OutputDebugString(fmt::format(L"{},{},{},{}\n",
|
||||
rect.left, rect.top, rect.right, rect.bottom).c_str());
|
||||
}
|
||||
|
|
@ -211,7 +214,7 @@ static void ValidateOptimize(const SmallVectorImpl<Rect>& originRects, const Sma
|
|||
}
|
||||
#endif
|
||||
|
||||
void DirtyRectsOptimizer::Execute(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
||||
void DirtyRectsOptimizer::Execute(SmallVectorImpl<RectU>& dirtyRects) noexcept {
|
||||
uint32_t rectCount = (uint32_t)dirtyRects.size();
|
||||
if (rectCount <= 1) {
|
||||
return;
|
||||
|
|
@ -219,7 +222,7 @@ void DirtyRectsOptimizer::Execute(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
|||
|
||||
#ifdef MP_DEBUG_INFO
|
||||
auto se = wil::scope_exit(std::bind_front(ValidateOptimize, DEBUG_INFO.validateDirtyRectsOptimizer ?
|
||||
SmallVector<Rect>(dirtyRects.begin(), dirtyRects.end()) : SmallVector<Rect>(), std::ref(dirtyRects)));
|
||||
SmallVector<RectU>(dirtyRects.begin(), dirtyRects.end()) : SmallVector<RectU>(), std::ref(dirtyRects)));
|
||||
#endif
|
||||
|
||||
if (rectCount <= MAX_CAPTURE_DIRTY_RECT_COUNT * 4) {
|
||||
|
|
@ -230,7 +233,7 @@ void DirtyRectsOptimizer::Execute(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
|||
// 深度优化的复杂度为 n^4,输入矩形数量太多时应削减。花太多时间优化脏矩形是得不偿失的
|
||||
constexpr uint32_t DEEP_OPTIMIZE_LIMIT = MAX_CAPTURE_DIRTY_RECT_COUNT * 2;
|
||||
if (rectCount > DEEP_OPTIMIZE_LIMIT) {
|
||||
Rect& lastRect = dirtyRects[DEEP_OPTIMIZE_LIMIT - 1];
|
||||
RectU& lastRect = dirtyRects[DEEP_OPTIMIZE_LIMIT - 1];
|
||||
for (auto it = dirtyRects.begin() + DEEP_OPTIMIZE_LIMIT; it != dirtyRects.end(); ++it) {
|
||||
lastRect = RectHelper::Union(lastRect, *it);
|
||||
}
|
||||
|
|
@ -255,15 +258,15 @@ void DirtyRectsOptimizer::Execute(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
|||
// 遍历所有的两两合并找出总像素数最少的
|
||||
for (uint32_t i = 0; i < rectCount; ++i) {
|
||||
for (uint32_t j = i + 1; j < rectCount; ++j) {
|
||||
const Rect& rect1 = dirtyRects[i];
|
||||
const Rect& rect2 = dirtyRects[j];
|
||||
const RectU& rect1 = dirtyRects[i];
|
||||
const RectU& rect2 = dirtyRects[j];
|
||||
|
||||
// 两个矩形必须相交才有优化的可能,但脏矩形数量过多时需要强制合并
|
||||
if (!RectHelper::IsOverlap(rect1, rect2) && rectCount <= MAX_CAPTURE_DIRTY_RECT_COUNT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rect unionedRect = RectHelper::Union(rect1, rect2);
|
||||
RectU unionedRect = RectHelper::Union(rect1, rect2);
|
||||
uint32_t newTotalPixels = 0;
|
||||
uint32_t newRectCount = 0;
|
||||
bool optimized = false;
|
||||
|
|
@ -274,7 +277,7 @@ void DirtyRectsOptimizer::Execute(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
|||
continue;
|
||||
}
|
||||
|
||||
Rect curRect = dirtyRects[k];
|
||||
RectU curRect = dirtyRects[k];
|
||||
if (OptimizeDirtyRectPair(curRect, unionedRect)) {
|
||||
optimized = true;
|
||||
}
|
||||
|
|
@ -326,12 +329,12 @@ void DirtyRectsOptimizer::Execute(SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
|||
|
||||
#ifdef _DEBUG
|
||||
static Ignore _ = [] {
|
||||
auto rectComp = [](const Rect& l, const Rect& r) {
|
||||
auto rectComp = [](const RectU& l, const RectU& r) {
|
||||
return std::tuple(l.left, l.top, l.right, l.bottom) <
|
||||
std::tuple(r.left, r.top, r.right, r.bottom);
|
||||
};
|
||||
|
||||
SmallVector<Rect, 0> dirtyRects;
|
||||
SmallVector<RectU, 0> dirtyRects;
|
||||
dirtyRects.reserve(16);
|
||||
|
||||
dirtyRects.emplace_back(0, 0, 2, 2);
|
||||
|
|
@ -342,15 +345,15 @@ static Ignore _ = [] {
|
|||
BasicOptimize(dirtyRects);
|
||||
std::sort(dirtyRects.begin(), dirtyRects.end(), rectComp);
|
||||
assert(dirtyRects.size() == 2);
|
||||
assert((dirtyRects[0] == Rect{ 0, 0, 2, 2 }));
|
||||
assert((dirtyRects[1] == Rect{ 1, 1, 4, 4 }));
|
||||
assert((dirtyRects[0] == RectU{ 0, 0, 2, 2 }));
|
||||
assert((dirtyRects[1] == RectU{ 1, 1, 4, 4 }));
|
||||
|
||||
dirtyRects.clear();
|
||||
dirtyRects.emplace_back(0, 0, 1, 1);
|
||||
dirtyRects.emplace_back(0, 0, 2, 2);
|
||||
BasicOptimize(dirtyRects);
|
||||
assert(dirtyRects.size() == 1);
|
||||
assert((dirtyRects[0] == Rect{ 0, 0, 2, 2 }));
|
||||
assert((dirtyRects[0] == RectU{ 0, 0, 2, 2 }));
|
||||
|
||||
return Ignore();
|
||||
}();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Magpie {
|
|||
|
||||
struct DirtyRectsOptimizer {
|
||||
// 尝试减少脏矩形数量和总像素数
|
||||
static void Execute(SmallVectorImpl<Rect>& dirtyRects) noexcept;
|
||||
static void Execute(SmallVectorImpl<RectU>& dirtyRects) noexcept;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ bool DuplicateFrameChecker::Initialize(
|
|||
ID3D11Device5* d3d11Device,
|
||||
ID3D11DeviceContext4* d3d11DC,
|
||||
const ColorInfo& colorInfo,
|
||||
Size frameSize,
|
||||
SizeU frameSize,
|
||||
uint32_t captureFrameCount,
|
||||
bool disableBoundsChecking
|
||||
) noexcept {
|
||||
|
|
@ -138,7 +138,7 @@ bool DuplicateFrameChecker::Initialize(
|
|||
HRESULT DuplicateFrameChecker::CheckFrame(
|
||||
ID3D11Texture2D* frameResource,
|
||||
uint32_t frameIdx,
|
||||
SmallVectorImpl<Rect>& dirtyRects
|
||||
SmallVectorImpl<RectU>& dirtyRects
|
||||
) noexcept {
|
||||
assert(!dirtyRects.empty() && dirtyRects.size() <= MAX_CAPTURE_DIRTY_RECT_COUNT);
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ HRESULT DuplicateFrameChecker::CheckFrame(
|
|||
|
||||
if (_isBoundsCheckingDisabled) {
|
||||
// 确保捕获帧右下两边没有多余像素
|
||||
for (const Rect& rect : dirtyRects) {
|
||||
for (const RectU& rect : dirtyRects) {
|
||||
assert(rect.right == desc.Width && rect.bottom == desc.Height);
|
||||
}
|
||||
}
|
||||
|
|
@ -212,7 +212,7 @@ HRESULT DuplicateFrameChecker::CheckFrame(
|
|||
#ifdef MP_DEBUG_INFO
|
||||
if (DEBUG_INFO.enableStatisticsForDynamicDuplicateFrameDetection) {
|
||||
// 预测此帧不会重复,验证是否正确
|
||||
SmallVector<Rect> tempRects(dirtyRects.begin(), dirtyRects.end());
|
||||
SmallVector<RectU> tempRects(dirtyRects.begin(), dirtyRects.end());
|
||||
HRESULT hr = _CheckDirtyRects(frameIdx, tempRects);
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("_CheckDirtyRects 失败", hr);
|
||||
|
|
@ -240,7 +240,10 @@ void DuplicateFrameChecker::OnCaptureStopped() noexcept {
|
|||
std::fill(_frameSrvs.begin(), _frameSrvs.end(), nullptr);
|
||||
}
|
||||
|
||||
HRESULT DuplicateFrameChecker::_CheckDirtyRects(uint32_t newFrameIdx, SmallVectorImpl<Rect>& dirtyRects) noexcept {
|
||||
HRESULT DuplicateFrameChecker::_CheckDirtyRects(
|
||||
uint32_t newFrameIdx,
|
||||
SmallVectorImpl<RectU>& dirtyRects
|
||||
) noexcept {
|
||||
assert(dirtyRects.size() <= MAX_CAPTURE_DIRTY_RECT_COUNT);
|
||||
|
||||
{
|
||||
|
|
@ -261,7 +264,7 @@ HRESULT DuplicateFrameChecker::_CheckDirtyRects(uint32_t newFrameIdx, SmallVecto
|
|||
++_curTargetValue;
|
||||
|
||||
for (uint32_t i = 0; i < dirtyRectCount; ++i) {
|
||||
const Rect& dirtyRect = dirtyRects[i];
|
||||
const RectU& dirtyRect = dirtyRects[i];
|
||||
|
||||
alignas(32) DirectXHelper::Constant32 constants[] = {
|
||||
{.uintVal = dirtyRect.left},
|
||||
|
|
@ -287,7 +290,7 @@ HRESULT DuplicateFrameChecker::_CheckDirtyRects(uint32_t newFrameIdx, SmallVecto
|
|||
_deviceContext->CSSetConstantBuffers1(0, 1, &buffer, &firstConstant, &numConstants);
|
||||
}
|
||||
|
||||
const Rect& dirtyRect = dirtyRects[i];
|
||||
const RectU& dirtyRect = dirtyRects[i];
|
||||
_deviceContext->Dispatch(
|
||||
(dirtyRect.right - dirtyRect.left + DUP_FRAME_DISPATCH_BLOCK_SIZE - 1) / DUP_FRAME_DISPATCH_BLOCK_SIZE,
|
||||
(dirtyRect.bottom - dirtyRect.top + DUP_FRAME_DISPATCH_BLOCK_SIZE - 1) / DUP_FRAME_DISPATCH_BLOCK_SIZE,
|
||||
|
|
|
|||
|
|
@ -16,24 +16,28 @@ public:
|
|||
ID3D11Device5* d3d11Device,
|
||||
ID3D11DeviceContext4* d3d11DC,
|
||||
const ColorInfo& colorInfo,
|
||||
Size frameSize,
|
||||
SizeU frameSize,
|
||||
uint32_t captureFrameCount,
|
||||
bool disableBoundsChecking
|
||||
) noexcept;
|
||||
|
||||
HRESULT CheckFrame(ID3D11Texture2D* frameResource, uint32_t frameIdx, SmallVectorImpl<Rect>& dirtyRects) noexcept;
|
||||
HRESULT CheckFrame(
|
||||
ID3D11Texture2D* frameResource,
|
||||
uint32_t frameIdx,
|
||||
SmallVectorImpl<RectU>& dirtyRects
|
||||
) noexcept;
|
||||
|
||||
void OnFrameAdopted(uint32_t frameIdx) noexcept;
|
||||
|
||||
void OnCaptureStopped() noexcept;
|
||||
|
||||
private:
|
||||
HRESULT _CheckDirtyRects(uint32_t newFrameIdx, SmallVectorImpl<Rect>& dirtyRects) noexcept;
|
||||
HRESULT _CheckDirtyRects(uint32_t newFrameIdx, SmallVectorImpl<RectU>& dirtyRects) noexcept;
|
||||
|
||||
ID3D11Device5* _device = nullptr;
|
||||
ID3D11DeviceContext4* _deviceContext = nullptr;
|
||||
|
||||
Size _frameSize{};
|
||||
SizeU _frameSize{};
|
||||
|
||||
winrt::com_ptr<ID3D11ComputeShader> _dupFrameCS;
|
||||
winrt::com_ptr<ID3D11Buffer> _constantBuffer;
|
||||
|
|
|
|||
|
|
@ -21,11 +21,13 @@ public:
|
|||
|
||||
virtual bool Bind(
|
||||
ID3D12Resource* inputResource,
|
||||
Size inputSize,
|
||||
SizeU inputSize,
|
||||
const ColorInfo& colorInfo,
|
||||
Size& outputSize
|
||||
SizeU& outputSize
|
||||
) noexcept = 0;
|
||||
|
||||
virtual bool IsReady() noexcept = 0;
|
||||
|
||||
virtual HRESULT Draw(
|
||||
ComputeContext& computeContext,
|
||||
uint32_t inputSrvOffset,
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ namespace Magpie {
|
|||
bool EffectsDrawer::Initialize(
|
||||
D3D12Context& d3d12Context,
|
||||
const ColorInfo& colorInfo,
|
||||
Size inputSize,
|
||||
Size rendererSize
|
||||
SizeU inputSize,
|
||||
SizeU rendererSize
|
||||
) noexcept {
|
||||
_d3d12Context = &d3d12Context;
|
||||
_isScRGB = colorInfo.kind != winrt::AdvancedColorKind::StandardDynamicRange;
|
||||
|
|
@ -113,7 +113,7 @@ HRESULT EffectsDrawer::Draw(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
void EffectsDrawer::OnResized(Size rendererSize) noexcept {
|
||||
void EffectsDrawer::OnResized(SizeU rendererSize) noexcept {
|
||||
_outputSize = rendererSize;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ public:
|
|||
bool Initialize(
|
||||
D3D12Context& d3d12Context,
|
||||
const ColorInfo& colorInfo,
|
||||
Size inputSize,
|
||||
Size rendererSize
|
||||
SizeU inputSize,
|
||||
SizeU rendererSize
|
||||
) noexcept;
|
||||
|
||||
HRESULT Draw(
|
||||
|
|
@ -27,19 +27,19 @@ public:
|
|||
uint32_t outputUavOffset
|
||||
) noexcept;
|
||||
|
||||
Size GetOutputSize() const noexcept {
|
||||
SizeU GetOutputSize() const noexcept {
|
||||
return _outputSize;
|
||||
}
|
||||
|
||||
void OnResized(Size rendererSize) noexcept;
|
||||
void OnResized(SizeU rendererSize) noexcept;
|
||||
|
||||
void OnColorInfoChanged(const ColorInfo& colorInfo) noexcept;
|
||||
|
||||
private:
|
||||
D3D12Context* _d3d12Context = nullptr;
|
||||
|
||||
Size _inputSize{};
|
||||
Size _outputSize{};
|
||||
SizeU _inputSize{};
|
||||
SizeU _outputSize{};
|
||||
|
||||
std::optional<CatmullRomDrawer> _catmullRomDrawer;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "Logger.h"
|
||||
#include "StrHelper.h"
|
||||
#include "Win32Helper.h"
|
||||
#include <rapidhash.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
|
|
@ -67,7 +68,7 @@ winrt::fire_and_forget EffectsService::Initialize() {
|
|||
}
|
||||
|
||||
auto lock = srwLock.lock_exclusive();
|
||||
_effectsMap.emplace(effectNames[id], (uint32_t)_effects.size());
|
||||
_effectsMap.emplace(effectInfo.name, (uint32_t)_effects.size());
|
||||
_effects.emplace_back(std::move(effectInfo));
|
||||
}, nEffect);
|
||||
|
||||
|
|
@ -85,13 +86,115 @@ const std::vector<EffectInfo>& EffectsService::GetEffects() noexcept {
|
|||
return _effects;
|
||||
}
|
||||
|
||||
const EffectInfo* EffectsService::GetEffect(std::wstring_view name) noexcept {
|
||||
const EffectInfo* EffectsService::GetEffect(std::string_view name) noexcept {
|
||||
_WaitForInitialize();
|
||||
|
||||
auto it = _effectsMap.find(name);
|
||||
return it != _effectsMap.end() ? &_effects[it->second] : nullptr;
|
||||
}
|
||||
|
||||
static std::string GetLinearEffectName(std::string_view effectName) {
|
||||
std::string result(effectName);
|
||||
for (char& c : result) {
|
||||
if (c == '\\') {
|
||||
c = '#';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string GetCacheFileName(
|
||||
std::string_view linearEffectName,
|
||||
D3D_SHADER_MODEL shaderModel,
|
||||
ShaderEffectParserFlags flags,
|
||||
uint64_t hash
|
||||
) {
|
||||
// 缓存文件的命名: {效果名}_{shader model(4)}_{标志位(4)}_{哈希(16))}
|
||||
return fmt::format("{}\\{}_{:04x}_{:04x}_{:016x}",
|
||||
StrHelper::UTF16ToUTF8(CommonSharedConstants::CACHE_DIR),
|
||||
linearEffectName, (uint32_t)shaderModel, (uint32_t)flags, hash);
|
||||
}
|
||||
|
||||
std::string EffectsService::SubmitCompileShaderEffectTask(
|
||||
std::string_view effectName,
|
||||
const phmap::flat_hash_map<std::string, float>* inlineParams,
|
||||
D3D_SHADER_MODEL shaderModel,
|
||||
bool isFP16Enabled,
|
||||
bool isAdvancedColorEnabled
|
||||
) noexcept {
|
||||
std::string source;
|
||||
{
|
||||
std::wstring fileName = StrHelper::Concat(
|
||||
CommonSharedConstants::EFFECTS_DIR, L"\\", StrHelper::UTF8ToUTF16(effectName), L".hlsl");
|
||||
Win32Helper::ReadTextFile(fileName.c_str(), source);
|
||||
}
|
||||
|
||||
ShaderEffectParserOptions options = {
|
||||
.inlineParams = inlineParams,
|
||||
.shaderModel = shaderModel
|
||||
};
|
||||
if (isFP16Enabled) {
|
||||
options.flags |= ShaderEffectParserFlags::EnableFP16;
|
||||
}
|
||||
if (isAdvancedColorEnabled) {
|
||||
options.flags |= ShaderEffectParserFlags::EnableAdvancedColor;
|
||||
}
|
||||
|
||||
// 传给 ParseForDesc 的几个参数都会影响字节码,其中 shaderModel 和 flags 不需要参与哈希,
|
||||
// 它们影响缓存键,即缓存文件名。
|
||||
std::string byteCodeKey;
|
||||
byteCodeKey.append(source);
|
||||
if (inlineParams) {
|
||||
for (const auto& pair : *inlineParams) {
|
||||
byteCodeKey.append(fmt::format("|{}|{}", pair.first, std::lroundf(pair.second * 10000)));
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t hash = rapidhash(byteCodeKey.data(), byteCodeKey.size());
|
||||
|
||||
std::string cacheKey = GetCacheFileName(
|
||||
GetLinearEffectName(effectName), shaderModel, options.flags, hash);
|
||||
|
||||
if (!_shaderEffectCache.contains(cacheKey)) {
|
||||
_shaderEffectCache.emplace(cacheKey, _ShaderEffectMemCacheItem{});
|
||||
|
||||
ShaderEffectDesc effectDesc;
|
||||
ShaderEffectSource effectSource;
|
||||
std::string errorMsg = ShaderEffectParser::ParseForDesc(
|
||||
effectName,
|
||||
std::move(source),
|
||||
StrHelper::UTF16ToUTF8(CommonSharedConstants::EFFECTS_DIR),
|
||||
options,
|
||||
effectDesc,
|
||||
effectSource
|
||||
);
|
||||
if (errorMsg.empty()) {
|
||||
|
||||
} else {
|
||||
// 解析失败
|
||||
_shaderEffectCache.erase(cacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
bool EffectsService::GetTaskResult(std::string taskKey, const ShaderEffectDesc*& effectDesc) noexcept {
|
||||
auto it = _shaderEffectCache.find(taskKey);
|
||||
if (it == _shaderEffectCache.end()) {
|
||||
// 编译失败
|
||||
return false;
|
||||
}
|
||||
|
||||
if (it->second.lastAccess == std::numeric_limits<uint32_t>::max()) {
|
||||
// 尚未编译完成
|
||||
effectDesc = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return &it->second.effectDesc;
|
||||
}
|
||||
|
||||
void EffectsService::_WaitForInitialize() noexcept {
|
||||
if (_initializedCache) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ void FrameProducer::InitializeAsync(
|
|||
const ColorInfo& colorInfo,
|
||||
HMONITOR hMonSrc,
|
||||
const RECT& srcRect,
|
||||
Size rendererSize,
|
||||
Size& outputSize,
|
||||
SizeU rendererSize,
|
||||
SizeU& outputSize,
|
||||
SimpleTask<bool>& task
|
||||
) noexcept {
|
||||
_d3d12Context.CopyDevice(d3d12Context);
|
||||
|
|
@ -94,8 +94,8 @@ HRESULT FrameProducer::ConsumerEndFrame(
|
|||
}
|
||||
|
||||
void FrameProducer::OnResizedAsync(
|
||||
Size rendererSize,
|
||||
Size& outputSize,
|
||||
SizeU rendererSize,
|
||||
SizeU& outputSize,
|
||||
SimpleTask<HRESULT>& task
|
||||
) noexcept {
|
||||
_dispatcher.TryEnqueue([&, rendererSize] {
|
||||
|
|
@ -220,8 +220,8 @@ void FrameProducer::_ProducerThreadProc(
|
|||
const ColorInfo& colorInfo,
|
||||
HMONITOR hMonSrc,
|
||||
RECT srcRect,
|
||||
Size rendererSize,
|
||||
Size& outputSize,
|
||||
SizeU rendererSize,
|
||||
SizeU& outputSize,
|
||||
SimpleTask<bool>& initializeTask
|
||||
) noexcept {
|
||||
#ifdef _DEBUG
|
||||
|
|
@ -319,8 +319,8 @@ bool FrameProducer::_Initialize(
|
|||
const ColorInfo& colorInfo,
|
||||
HMONITOR hMonSrc,
|
||||
const RECT& srcRect,
|
||||
Size rendererSize,
|
||||
Size& outputSize
|
||||
SizeU rendererSize,
|
||||
SizeU& outputSize
|
||||
) noexcept {
|
||||
winrt::init_apartment(winrt::apartment_type::single_threaded);
|
||||
|
||||
|
|
@ -365,7 +365,7 @@ bool FrameProducer::_Initialize(
|
|||
}
|
||||
|
||||
{
|
||||
const Size inputSize = {
|
||||
const SizeU inputSize = {
|
||||
uint32_t(srcRect.right - srcRect.left),
|
||||
uint32_t(srcRect.bottom - srcRect.top)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ public:
|
|||
const ColorInfo& colorInfo,
|
||||
HMONITOR hMonSrc,
|
||||
const RECT& srcRect,
|
||||
Size rendererSize,
|
||||
Size& outputSize,
|
||||
SizeU rendererSize,
|
||||
SizeU& outputSize,
|
||||
SimpleTask<bool>& task
|
||||
) noexcept;
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ public:
|
|||
uint64_t fenceValueToSignal
|
||||
) const noexcept;
|
||||
|
||||
void OnResizedAsync(Size rendererSize, Size& outputSize, SimpleTask<HRESULT>& task) noexcept;
|
||||
void OnResizedAsync(SizeU rendererSize, SizeU& outputSize, SimpleTask<HRESULT>& task) noexcept;
|
||||
|
||||
void OnColorInfoChangedAsync(const ColorInfo& colorInfo, SimpleTask<HRESULT>& task) noexcept;
|
||||
|
||||
|
|
@ -55,8 +55,8 @@ private:
|
|||
const ColorInfo& colorInfo,
|
||||
HMONITOR hMonSrc,
|
||||
RECT srcRect,
|
||||
Size rendererSize,
|
||||
Size& outputSize,
|
||||
SizeU rendererSize,
|
||||
SizeU& outputSize,
|
||||
SimpleTask<bool>& initializeTask
|
||||
) noexcept;
|
||||
|
||||
|
|
@ -64,8 +64,8 @@ private:
|
|||
const ColorInfo& colorInfo,
|
||||
HMONITOR hMonSrc,
|
||||
const RECT& srcRect,
|
||||
Size rendererSize,
|
||||
Size& outputSize
|
||||
SizeU rendererSize,
|
||||
SizeU& outputSize
|
||||
) noexcept;
|
||||
|
||||
void _CreateInputDescriptors() noexcept;
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
#include "Logger.h"
|
||||
#include "ScalingWindow.h"
|
||||
#include "DebugInfo.h"
|
||||
#include "DescriptorHeap.h"
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
bool FrameRingBuffer::Initialize(
|
||||
D3D12Context& d3d12Context,
|
||||
Size size,
|
||||
SizeU size,
|
||||
const ColorInfo& colorInfo
|
||||
) noexcept {
|
||||
_d3d12Context = &d3d12Context;
|
||||
|
|
@ -206,7 +205,7 @@ uint64_t FrameRingBuffer::GetLatestFrameNumber() const noexcept {
|
|||
return _producerFence->GetCompletedValue();
|
||||
}
|
||||
|
||||
HRESULT FrameRingBuffer::OnResized(Size size) noexcept {
|
||||
HRESULT FrameRingBuffer::OnResized(SizeU size) noexcept {
|
||||
_size = size;
|
||||
|
||||
HRESULT hr = _CreateBuffers();
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public:
|
|||
|
||||
bool Initialize(
|
||||
D3D12Context& d3d12Context,
|
||||
Size size,
|
||||
SizeU size,
|
||||
const ColorInfo& colorInfo
|
||||
) noexcept;
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
uint64_t GetLatestFrameNumber() const noexcept;
|
||||
|
||||
HRESULT OnResized(Size size) noexcept;
|
||||
HRESULT OnResized(SizeU size) noexcept;
|
||||
|
||||
HRESULT OnColorInfoChanged(const ColorInfo& colorInfo) noexcept;
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ private:
|
|||
uint64_t _curConsumerFenceValue = 0;
|
||||
winrt::com_ptr<ID3D12Fence1> _producerFence;
|
||||
|
||||
Size _size{};
|
||||
SizeU _size{};
|
||||
bool _isScRGB = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ bool GraphicsCaptureFrameSource::Initialize(
|
|||
_d3d11Device.get(),
|
||||
_d3d11DC.get(),
|
||||
colorInfo,
|
||||
Size{ _frameBox.right, _frameBox.bottom },
|
||||
SizeU{ _frameBox.right, _frameBox.bottom },
|
||||
captureFrameCount,
|
||||
!_isDirtyRegionSupported
|
||||
)) {
|
||||
|
|
@ -438,7 +438,7 @@ HRESULT GraphicsCaptureFrameSource::Update(uint32_t& outputIdx) noexcept {
|
|||
_captureFrameResourceTable[_newCaptureFrameResourceIdx].second.get();
|
||||
|
||||
// curSlot.output 到 curFrameResource 的脏矩形
|
||||
SmallVector<Rect> allDirtyRects;
|
||||
SmallVector<RectU> allDirtyRects;
|
||||
if (_isDirtyRegionSupported) {
|
||||
for (const _FrameResourceSlot& slot : _slots) {
|
||||
allDirtyRects.append(slot.dirtyRects);
|
||||
|
|
@ -447,7 +447,7 @@ HRESULT GraphicsCaptureFrameSource::Update(uint32_t& outputIdx) noexcept {
|
|||
|
||||
#ifdef _DEBUG
|
||||
// 所有脏矩形应在 _frameBox 内
|
||||
for (const Rect& dirtyRect : allDirtyRects) {
|
||||
for (const RectU& dirtyRect : allDirtyRects) {
|
||||
assert(dirtyRect.left >= _frameBox.left && dirtyRect.top >= _frameBox.top &&
|
||||
dirtyRect.right <= _frameBox.right && dirtyRect.bottom <= _frameBox.bottom);
|
||||
}
|
||||
|
|
@ -505,7 +505,7 @@ HRESULT GraphicsCaptureFrameSource::Update(uint32_t& outputIdx) noexcept {
|
|||
CD3DX12_TEXTURE_COPY_LOCATION dest(curCASlot.bridgeResource.get(), 0);
|
||||
|
||||
if (_isDirtyRegionSupported) {
|
||||
for (const Rect& dirtyRect : allDirtyRects) {
|
||||
for (const RectU& dirtyRect : allDirtyRects) {
|
||||
D3D12_BOX box = {
|
||||
.left = dirtyRect.left,
|
||||
.top = dirtyRect.top,
|
||||
|
|
@ -554,7 +554,7 @@ HRESULT GraphicsCaptureFrameSource::Update(uint32_t& outputIdx) noexcept {
|
|||
return false;
|
||||
}
|
||||
|
||||
const Rect& dirtyRect = allDirtyRects[0];
|
||||
const RectU& dirtyRect = allDirtyRects[0];
|
||||
return dirtyRect.left == _frameBox.left && dirtyRect.top == _frameBox.top &&
|
||||
dirtyRect.right == _frameBox.right && dirtyRect.bottom == _frameBox.bottom;
|
||||
};
|
||||
|
|
@ -565,7 +565,7 @@ HRESULT GraphicsCaptureFrameSource::Update(uint32_t& outputIdx) noexcept {
|
|||
CD3DX12_TEXTURE_COPY_LOCATION src(curCASlot.sharedResource.get(), 0);
|
||||
CD3DX12_TEXTURE_COPY_LOCATION dest(curSlot.output.get(), 0);
|
||||
|
||||
for (const Rect& dirtyRect : allDirtyRects) {
|
||||
for (const RectU& dirtyRect : allDirtyRects) {
|
||||
D3D12_BOX box = {
|
||||
.left = dirtyRect.left - _frameBox.left,
|
||||
.top = dirtyRect.top - _frameBox.top,
|
||||
|
|
@ -582,7 +582,7 @@ HRESULT GraphicsCaptureFrameSource::Update(uint32_t& outputIdx) noexcept {
|
|||
CD3DX12_TEXTURE_COPY_LOCATION dest(curSlot.output.get(), 0);
|
||||
|
||||
if (_isDirtyRegionSupported) {
|
||||
for (const Rect& dirtyRect : allDirtyRects) {
|
||||
for (const RectU& dirtyRect : allDirtyRects) {
|
||||
D3D12_BOX box = {
|
||||
.left = dirtyRect.left,
|
||||
.top = dirtyRect.top,
|
||||
|
|
@ -1121,7 +1121,7 @@ void GraphicsCaptureFrameSource::_Direct3D11CaptureFramePool_FrameArrived(
|
|||
const winrt::IInspectable&
|
||||
) {
|
||||
winrt::Direct3D11CaptureFrame frame{ nullptr };
|
||||
SmallVector<Rect> dirtyRects;
|
||||
SmallVector<RectU> dirtyRects;
|
||||
|
||||
// 取最新帧
|
||||
while (true) {
|
||||
|
|
|
|||
|
|
@ -94,12 +94,12 @@ private:
|
|||
// 不要在持有 _latestFrameLock 时释放 _latestFrame 或调用其中的方法,和 WGC 内部的
|
||||
// 同步机制冲突。如果此时_Direct3D11CaptureFramePool_FrameArrived 正在执行会死锁。
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFrame _latestFrame{ nullptr };
|
||||
SmallVector<Rect> _latestFrameDirtyRects;
|
||||
SmallVector<RectU> _latestFrameDirtyRects;
|
||||
|
||||
std::vector<std::pair<ID3D11Texture2D*, winrt::com_ptr<ID3D12Resource>>> _captureFrameResourceTable;
|
||||
std::unique_ptr<DuplicateFrameChecker> _duplicateFrameChecker;
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFrame _newFrame{ nullptr };
|
||||
SmallVector<Rect> _newFrameDirtyRects;
|
||||
SmallVector<RectU> _newFrameDirtyRects;
|
||||
uint32_t _newCaptureFrameResourceIdx = 0;
|
||||
|
||||
struct _FrameCrossAdapterResourceSlot {
|
||||
|
|
@ -121,7 +121,7 @@ private:
|
|||
// 保留引用防止 WGC 再次写入
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFrame captureFrame{ nullptr };
|
||||
uint32_t captureFrameResourceIdx = 0;
|
||||
SmallVector<Rect> dirtyRects;
|
||||
SmallVector<RectU> dirtyRects;
|
||||
winrt::com_ptr<ID3D12Resource> output;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -68,14 +68,12 @@
|
|||
<ClInclude Include="include\EffectInfo.h" />
|
||||
<ClInclude Include="include\EffectsService.h" />
|
||||
<ClInclude Include="include\LocalizationService.h" />
|
||||
<ClInclude Include="include\ShaderEffectParser.h" />
|
||||
<ClInclude Include="ShaderEffectCompilerService.h" />
|
||||
<ClInclude Include="ShaderEffectDesc.h" />
|
||||
<ClInclude Include="ShaderEffectDrawer.h" />
|
||||
<ClInclude Include="GraphicsCaptureFrameSource.h" />
|
||||
<ClInclude Include="D3D12Context.h" />
|
||||
<ClInclude Include="include\DirectXHelper.h" />
|
||||
<ClInclude Include="include\EffectDesc.h" />
|
||||
<ClInclude Include="include\ScalingOptions.h" />
|
||||
<ClInclude Include="include\ScalingRuntime.h" />
|
||||
<ClInclude Include="include\Win32Helper.h" />
|
||||
|
|
@ -87,6 +85,7 @@
|
|||
<ClInclude Include="Renderer.h" />
|
||||
<ClInclude Include="ScalingWindow.h" />
|
||||
<ClInclude Include="FrameRingBuffer.h" />
|
||||
<ClInclude Include="ShaderEffectParser.h" />
|
||||
<ClInclude Include="SrcTracker.h" />
|
||||
<ClInclude Include="StepTimer.h" />
|
||||
<ClInclude Include="SwapChainPresenter.h" />
|
||||
|
|
|
|||
|
|
@ -33,9 +33,6 @@
|
|||
</ClInclude>
|
||||
<ClInclude Include="ScalingWindow.h" />
|
||||
<ClInclude Include="CursorManager.h" />
|
||||
<ClInclude Include="include\EffectDesc.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\ScalingOptions.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -106,9 +103,6 @@
|
|||
<ClInclude Include="include\EffectInfo.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\ShaderEffectParser.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ShaderEffectCompilerService.h">
|
||||
<Filter>Services</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -137,6 +131,7 @@
|
|||
<ClInclude Include="include\LocalizationService.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ShaderEffectParser.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ScalingRuntime.cpp" />
|
||||
|
|
|
|||
|
|
@ -3,23 +3,23 @@
|
|||
namespace Magpie {
|
||||
|
||||
struct RectHelper {
|
||||
static bool IsOverlap(const Rect& r1, const Rect& r2) noexcept {
|
||||
static bool IsOverlap(const RectU& r1, const RectU& r2) noexcept {
|
||||
return r1.right > r2.left && r1.bottom > r2.top && r1.left < r2.right && r1.top < r2.bottom;
|
||||
}
|
||||
|
||||
static bool Contains(const Rect& r1, const Rect& r2) noexcept {
|
||||
static bool Contains(const RectU& r1, const RectU& r2) noexcept {
|
||||
return r1.left <= r2.left && r1.top <= r2.top && r1.right >= r2.right && r1.bottom >= r2.bottom;
|
||||
}
|
||||
|
||||
static bool Contains(const Rect& rect, Point p) noexcept {
|
||||
static bool Contains(const RectU& rect, PointU p) noexcept {
|
||||
return p.x >= rect.left && p.x < rect.right && p.y >= rect.top && p.y < rect.bottom;
|
||||
}
|
||||
|
||||
static bool IsEmpty(const Rect& rect) noexcept {
|
||||
static bool IsEmpty(const RectU& rect) noexcept {
|
||||
return rect.left == rect.right || rect.top == rect.bottom;
|
||||
}
|
||||
|
||||
static bool Intersect(Rect& result, const Rect& r1, const Rect& r2) noexcept {
|
||||
static bool Intersect(RectU& result, const RectU& r1, const RectU& r2) noexcept {
|
||||
// 计算重叠部分
|
||||
result.left = std::max(r1.left, r2.left);
|
||||
result.top = std::max(r1.top, r2.top);
|
||||
|
|
@ -30,12 +30,12 @@ struct RectHelper {
|
|||
return result.left < result.right && result.top < result.bottom;
|
||||
}
|
||||
|
||||
static Rect Union(const Rect& r1, const Rect& r2) noexcept {
|
||||
return Rect{ std::min(r1.left, r2.left), std::min(r1.top, r2.top),
|
||||
static RectU Union(const RectU& r1, const RectU& r2) noexcept {
|
||||
return RectU{ std::min(r1.left, r2.left), std::min(r1.top, r2.top),
|
||||
std::max(r1.right, r2.right), std::max(r1.bottom, r2.bottom) };
|
||||
}
|
||||
|
||||
static uint32_t CalcArea(const Rect& rect) noexcept {
|
||||
static uint32_t CalcArea(const RectU& rect) noexcept {
|
||||
assert(rect.right >= rect.left && rect.bottom >= rect.top);
|
||||
return (rect.right - rect.left) * (rect.bottom - rect.top);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,12 +120,12 @@ ScalingError Renderer::Initialize(
|
|||
return ScalingError::ScalingFailedGeneral;
|
||||
}
|
||||
|
||||
const Size rendererSize = {
|
||||
const SizeU rendererSize = {
|
||||
uint32_t(rendererRect.right - rendererRect.left),
|
||||
uint32_t(rendererRect.bottom - rendererRect.top)
|
||||
};
|
||||
|
||||
Size outputSize;
|
||||
SizeU outputSize;
|
||||
SimpleTask<bool> task;
|
||||
_frameProducer.InitializeAsync(
|
||||
_d3d12Context, _colorInfo, hMonitor, srcRect, rendererSize, outputSize, task);
|
||||
|
|
@ -239,12 +239,12 @@ void Renderer::OnResized(const RECT& rendererRect, RECT& destRect) noexcept {
|
|||
return;
|
||||
}
|
||||
|
||||
const Size rendererSize = {
|
||||
const SizeU rendererSize = {
|
||||
uint32_t(rendererRect.right - rendererRect.left),
|
||||
uint32_t(rendererRect.bottom - rendererRect.top)
|
||||
};
|
||||
|
||||
Size outputSize;
|
||||
SizeU outputSize;
|
||||
SimpleTask<HRESULT> task;
|
||||
_frameProducer.OnResizedAsync(rendererSize, outputSize, task);
|
||||
|
||||
|
|
@ -524,7 +524,7 @@ HRESULT Renderer::_RenderImpl(bool waitForGpu) noexcept {
|
|||
|
||||
_graphicsContext.SetRootSignature(_copyRootSignature.get());
|
||||
|
||||
const Size rendererSize = _presenter->GetSize();
|
||||
const SizeU rendererSize = _presenter->GetSize();
|
||||
|
||||
{
|
||||
float outputWidth = float(_outputRect.right - _outputRect.left);
|
||||
|
|
@ -593,9 +593,9 @@ HRESULT Renderer::_RenderImpl(bool waitForGpu) noexcept {
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
void Renderer::_UpdateOutputRect(Size outputSize) noexcept {
|
||||
void Renderer::_UpdateOutputRect(SizeU outputSize) noexcept {
|
||||
// TODO: 窗口模式缩放始终填充画面
|
||||
const Size rendererSize = _presenter->GetSize();
|
||||
const SizeU rendererSize = _presenter->GetSize();
|
||||
OutputAlignment alignment = ScalingWindow::Get().Options().outputAlignment;
|
||||
|
||||
using enum OutputAlignment;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public:
|
|||
bool* waitingForFirstFrame = nullptr
|
||||
) noexcept;
|
||||
|
||||
const Rect& GetOutputRect() const noexcept {
|
||||
const RectU& GetOutputRect() const noexcept {
|
||||
return _outputRect;
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ private:
|
|||
|
||||
HRESULT _RenderImpl(bool waitForGpu = false) noexcept;
|
||||
|
||||
void _UpdateOutputRect(Size outputSize) noexcept;
|
||||
void _UpdateOutputRect(SizeU outputSize) noexcept;
|
||||
|
||||
bool _CheckResult(bool success, std::string_view errorMsg) noexcept;
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ private:
|
|||
winrt::DisplayInformation _displayInfo{ nullptr };
|
||||
winrt::DisplayInformation::AdvancedColorInfoChanged_revoker _acInfoChangedRevoker;
|
||||
|
||||
Rect _outputRect{};
|
||||
RectU _outputRect{};
|
||||
|
||||
// 由多个 D3D12Context 共享
|
||||
DescriptorHeap _csuDescriptorHeap;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include "SmallVector.h"
|
||||
#include <variant>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
|
|
@ -39,7 +38,6 @@ enum class EffectSamplerAddressType {
|
|||
};
|
||||
|
||||
struct ShaderEffectSamplerDesc {
|
||||
std::string name;
|
||||
EffectSamplerFilterType filterType = EffectSamplerFilterType::Point;
|
||||
EffectSamplerAddressType addressType = EffectSamplerAddressType::Clamp;
|
||||
};
|
||||
|
|
@ -51,41 +49,25 @@ enum class ShaderEffectPassFlags {
|
|||
DEFINE_ENUM_FLAG_OPERATORS(ShaderEffectPassFlags)
|
||||
|
||||
struct ShaderEffectPassDesc {
|
||||
winrt::com_ptr<ID3DBlob> byteCode;
|
||||
// 0: INPUT
|
||||
// 1: OUTPUT
|
||||
// 2+: 中间纹理
|
||||
SmallVector<uint32_t> inputs;
|
||||
SmallVector<uint32_t> outputs;
|
||||
std::array<uint32_t, 3> numThreads{};
|
||||
Size blockSize{};
|
||||
SizeU blockSize{};
|
||||
ShaderEffectPassFlags flags = ShaderEffectPassFlags::None;
|
||||
|
||||
// 用于在叠加层中显示
|
||||
std::string desc;
|
||||
};
|
||||
|
||||
enum class ShaderEffectFlags {
|
||||
None = 0,
|
||||
UseDynamic = 1,
|
||||
// 用于在叠加层中显示
|
||||
UseFP16 = 1 << 1
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(ShaderEffectFlags)
|
||||
|
||||
struct ShaderEffectDesc {
|
||||
std::pair<std::string, std::string> outputSizeExprs;
|
||||
|
||||
std::vector<std::variant<float, int>> params;
|
||||
// 不包含 INPUT 和 OUTPUT
|
||||
std::vector<ShaderEffectTextureDesc> textures;
|
||||
std::vector<ShaderEffectSamplerDesc> samplers;
|
||||
std::vector<ShaderEffectPassDesc> passes;
|
||||
|
||||
float minFrameRate = 0.0f;
|
||||
ShaderEffectFlags flags = ShaderEffectFlags::None;
|
||||
|
||||
// 用于在叠加层中显示
|
||||
std::string name;
|
||||
SmallVector<ShaderEffectTextureDesc, 0> textures;
|
||||
SmallVector<ShaderEffectSamplerDesc> samplers;
|
||||
SmallVector<ShaderEffectPassDesc, 0> passes;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "pch.h"
|
||||
#include "ShaderEffectDrawer.h"
|
||||
#include "EffectsService.h"
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
|
|
@ -12,13 +13,17 @@ bool ShaderEffectDrawer::Initialize(
|
|||
|
||||
bool ShaderEffectDrawer::Bind(
|
||||
ID3D12Resource* /*inputResource*/,
|
||||
Size /*inputSize*/,
|
||||
SizeU /*inputSize*/,
|
||||
const ColorInfo& /*colorInfo*/,
|
||||
Size& /*outputSize*/
|
||||
SizeU& /*outputSize*/
|
||||
) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShaderEffectDrawer::IsReady() noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT ShaderEffectDrawer::Draw(
|
||||
ComputeContext& /*computeContext*/,
|
||||
uint32_t /*inputSrvOffset*/,
|
||||
|
|
|
|||
|
|
@ -14,11 +14,13 @@ public:
|
|||
|
||||
bool Bind(
|
||||
ID3D12Resource* inputResource,
|
||||
Size inputSize,
|
||||
SizeU inputSize,
|
||||
const ColorInfo& colorInfo,
|
||||
Size& outputSize
|
||||
SizeU& outputSize
|
||||
) noexcept override;
|
||||
|
||||
bool IsReady() noexcept override;
|
||||
|
||||
HRESULT Draw(
|
||||
ComputeContext& computeContext,
|
||||
uint32_t inputSrvOffset,
|
||||
|
|
|
|||
|
|
@ -432,10 +432,41 @@ static bool ResolveHeaderSortName(
|
|||
static bool ResolveHeaderUse(
|
||||
std::string_view& source,
|
||||
ParserState& state,
|
||||
void*
|
||||
void* data
|
||||
) noexcept {
|
||||
std::string_view flags;
|
||||
return GetNextStringUntilLineEnd<false>(source, state, flags);
|
||||
if (!GetNextStringUntilLineEnd<false>(source, state, flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr std::array FLAG_INFOS = {
|
||||
std::make_pair("DYNAMIC", EffectInfoFlags::UseDynamic)
|
||||
};
|
||||
|
||||
std::bitset<FLAG_INFOS.size()> processed;
|
||||
|
||||
for (std::string_view& token : StrHelper::Split(flags, ',')) {
|
||||
StrHelper::Trim(token);
|
||||
std::string flag = StrHelper::ToUpperCase(token);
|
||||
|
||||
auto it = std::find_if(FLAG_INFOS.begin(), FLAG_INFOS.end(), [&](const auto& flagInfo) {
|
||||
return flagInfo.first == flag;
|
||||
});
|
||||
if (it != FLAG_INFOS.end()) {
|
||||
size_t idx = it - FLAG_INFOS.begin();
|
||||
|
||||
if (processed[idx]) {
|
||||
return false;
|
||||
}
|
||||
processed[idx] = true;
|
||||
|
||||
((EffectInfo*)data)->flags |= it->second;
|
||||
} else {
|
||||
Logger::Get().Warn(StrHelper::Concat("未知的 USE 标志: ", token));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ResolveHeaderCapability(
|
||||
|
|
@ -449,9 +480,7 @@ static bool ResolveHeaderCapability(
|
|||
}
|
||||
|
||||
static constexpr std::array FLAG_INFOS = {
|
||||
// 以下为必需
|
||||
std::make_pair("FP16", EffectInfoFlags::SupportFP16),
|
||||
// 以下为可选
|
||||
std::make_pair("ADVANCEDCOLOR", EffectInfoFlags::SupportAdvancedColor)
|
||||
};
|
||||
|
||||
|
|
@ -474,7 +503,7 @@ static bool ResolveHeaderCapability(
|
|||
|
||||
((EffectInfo*)data)->flags |= it->second;
|
||||
} else {
|
||||
Logger::Get().Warn(StrHelper::Concat("使用了未知 CAPABILITY 标志: ", token));
|
||||
Logger::Get().Warn(StrHelper::Concat("未知的 CAPABILITY 标志: ", token));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -681,7 +710,12 @@ static bool ResolveParameter(
|
|||
return false;
|
||||
}
|
||||
|
||||
return source.empty();
|
||||
if (!source.empty()) {
|
||||
SetGeneralParseError(state, source, "\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ShaderEffectParser::ParseForInfo(
|
||||
|
|
@ -830,8 +864,8 @@ std::string ShaderEffectParser::ParseForInfo(
|
|||
return std::move(state.errorMsg);
|
||||
}
|
||||
|
||||
bool ShaderEffectParser::ParseForDesc(
|
||||
std::string&& name,
|
||||
std::string ShaderEffectParser::ParseForDesc(
|
||||
std::string_view name,
|
||||
std::string&& source,
|
||||
std::string&& workingFolder,
|
||||
const ShaderEffectParserOptions& /*options*/,
|
||||
|
|
@ -840,7 +874,6 @@ bool ShaderEffectParser::ParseForDesc(
|
|||
) noexcept {
|
||||
assert(!name.empty() && !source.empty() && !workingFolder.empty());
|
||||
|
||||
effectDesc.name = std::move(name);
|
||||
effectSource.workingFolder = std::move(workingFolder);
|
||||
|
||||
ParserState state = {
|
||||
|
|
@ -854,7 +887,7 @@ bool ShaderEffectParser::ParseForDesc(
|
|||
}
|
||||
// std::string_view sourceView(source);
|
||||
|
||||
return false;
|
||||
return std::move(state.errorMsg);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@ enum class ShaderEffectParserFlags {
|
|||
DEFINE_ENUM_FLAG_OPERATORS(ShaderEffectParserFlags)
|
||||
|
||||
struct ShaderEffectParserOptions {
|
||||
// 只在效果存在参数时影响字节码。为空表示不内联
|
||||
// 为空表示不内联
|
||||
const phmap::flat_hash_map<std::string, float>* inlineParams = nullptr;
|
||||
// 始终影响字节码
|
||||
D3D_SHADER_MODEL shaderModel = D3D_SHADER_MODEL_5_1;
|
||||
ShaderEffectParserFlags flags = ShaderEffectParserFlags::None;
|
||||
};
|
||||
|
|
@ -36,8 +35,8 @@ struct ShaderEffectParser {
|
|||
struct EffectInfo& effectInfo
|
||||
) noexcept;
|
||||
|
||||
static bool ParseForDesc(
|
||||
std::string&& name,
|
||||
static std::string ParseForDesc(
|
||||
std::string_view name,
|
||||
std::string&& source,
|
||||
std::string&& workingFolder,
|
||||
const ShaderEffectParserOptions& options,
|
||||
|
|
@ -29,7 +29,7 @@ SwapChainPresenter::~SwapChainPresenter() noexcept {
|
|||
bool SwapChainPresenter::Initialize(
|
||||
D3D12Context& d3d12Context,
|
||||
HWND hwndAttach,
|
||||
Size size,
|
||||
SizeU size,
|
||||
const ColorInfo& colorInfo
|
||||
) noexcept {
|
||||
_d3d12Context = &d3d12Context;
|
||||
|
|
@ -318,7 +318,7 @@ HRESULT SwapChainPresenter::EndFrame(bool waitForGpu) noexcept {
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SwapChainPresenter::OnResized(Size size) noexcept {
|
||||
HRESULT SwapChainPresenter::OnResized(SizeU size) noexcept {
|
||||
assert(size.width > 0 && size.height > 0 && size != _size);
|
||||
|
||||
_size = size;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public:
|
|||
bool Initialize(
|
||||
D3D12Context& graphicContext,
|
||||
HWND hwndAttach,
|
||||
Size size,
|
||||
SizeU size,
|
||||
const ColorInfo& colorInfo
|
||||
) noexcept;
|
||||
|
||||
|
|
@ -28,9 +28,9 @@ public:
|
|||
|
||||
HRESULT EndFrame(bool waitForGpu = false) noexcept;
|
||||
|
||||
Size GetSize() const noexcept { return _size; }
|
||||
SizeU GetSize() const noexcept { return _size; }
|
||||
|
||||
HRESULT OnResized(Size size) noexcept;
|
||||
HRESULT OnResized(SizeU size) noexcept;
|
||||
|
||||
void OnResizeStarted() noexcept;
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ private:
|
|||
wil::unique_event_nothrow _frameLatencyWaitableObject;
|
||||
std::vector<winrt::com_ptr<ID3D12Resource>> _frameBuffers;
|
||||
|
||||
Size _size{};
|
||||
SizeU _size{};
|
||||
uint32_t _bufferCount = 0;
|
||||
uint32_t _rtvBaseOffset = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t _rawRtvBaseOffset = std::numeric_limits<uint32_t>::max();
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
#pragma once
|
||||
#include "SmallVector.h"
|
||||
#include <d3dcommon.h>
|
||||
#include <variant>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
enum class EffectIntermediateTextureFormat {
|
||||
R32G32B32A32_FLOAT,
|
||||
R16G16B16A16_FLOAT,
|
||||
R16G16B16A16_UNORM,
|
||||
R16G16B16A16_SNORM,
|
||||
R32G32_FLOAT,
|
||||
R10G10B10A2_UNORM,
|
||||
R11G11B10_FLOAT,
|
||||
R8G8B8A8_UNORM,
|
||||
R8G8B8A8_SNORM,
|
||||
R16G16_FLOAT,
|
||||
R16G16_UNORM,
|
||||
R16G16_SNORM,
|
||||
R32_FLOAT,
|
||||
R8G8_UNORM,
|
||||
R8G8_SNORM,
|
||||
R16_FLOAT,
|
||||
R16_UNORM,
|
||||
R16_SNORM,
|
||||
R8_UNORM,
|
||||
R8_SNORM,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
struct EffectIntermediateTextureDesc {
|
||||
std::pair<std::string, std::string> sizeExpr;
|
||||
EffectIntermediateTextureFormat format = EffectIntermediateTextureFormat::UNKNOWN;
|
||||
std::string name;
|
||||
std::string source;
|
||||
};
|
||||
|
||||
enum class EffectSamplerFilterType {
|
||||
Linear,
|
||||
Point
|
||||
};
|
||||
|
||||
enum class EffectSamplerAddressType {
|
||||
Clamp,
|
||||
Wrap
|
||||
};
|
||||
|
||||
struct EffectSamplerDesc {
|
||||
EffectSamplerFilterType filterType = EffectSamplerFilterType::Linear;
|
||||
EffectSamplerAddressType addressType = EffectSamplerAddressType::Clamp;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct EffectConstant {
|
||||
T defaultValue;
|
||||
T minValue;
|
||||
T maxValue;
|
||||
T step;
|
||||
};
|
||||
|
||||
struct EffectParameterDesc {
|
||||
std::string name;
|
||||
std::string label;
|
||||
std::variant<EffectConstant<float>, EffectConstant<int>> constant;
|
||||
};
|
||||
|
||||
struct EffectPassFlags {
|
||||
static constexpr uint32_t PSStyle = 1;
|
||||
};
|
||||
|
||||
struct EffectPassDesc {
|
||||
winrt::com_ptr<ID3DBlob> cso;
|
||||
SmallVector<uint32_t> inputs;
|
||||
SmallVector<uint32_t> outputs;
|
||||
std::array<uint32_t, 3> numThreads{};
|
||||
std::pair<uint32_t, uint32_t> blockSize{};
|
||||
std::string desc;
|
||||
uint32_t flags = 0; // EffectPassFlags
|
||||
};
|
||||
|
||||
struct EffectFlags {
|
||||
// 效果本身的属性
|
||||
static constexpr uint32_t UseDynamic = 1;
|
||||
static constexpr uint32_t UseMulAdd = 1 << 1;
|
||||
static constexpr uint32_t SupportFP16 = 1 << 2;
|
||||
// 编译赋予的属性
|
||||
static constexpr uint32_t InlineParams = 1 << 16;
|
||||
static constexpr uint32_t FP16 = 1 << 17;
|
||||
};
|
||||
|
||||
struct EffectDesc {
|
||||
const std::pair<std::string, std::string>& GetOutputSizeExpr() const noexcept {
|
||||
return textures[1].sizeExpr;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string sortName; // 仅供 UI 使用
|
||||
|
||||
std::vector<EffectParameterDesc> params;
|
||||
// 0: INPUT
|
||||
// 1: OUTPUT
|
||||
// > 1: 中间纹理
|
||||
std::vector<EffectIntermediateTextureDesc> textures;
|
||||
std::vector<EffectSamplerDesc> samplers;
|
||||
std::vector<EffectPassDesc> passes;
|
||||
|
||||
uint32_t flags = 0; // EffectFlags
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ enum class EffectInfoFlags {
|
|||
None,
|
||||
SupportFP16 = 1,
|
||||
SupportAdvancedColor = 1 << 1,
|
||||
UseDynamic = 1 << 2
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(EffectInfoFlags)
|
||||
|
||||
|
|
@ -25,6 +26,8 @@ struct EffectInfo {
|
|||
std::vector<EffectInfoParameter> params;
|
||||
// 0 表示可以自由缩放
|
||||
uint32_t scaleFactor = 0;
|
||||
// 0 表示不限制
|
||||
uint32_t minFrameRate = 0;
|
||||
EffectInfoFlags flags = EffectInfoFlags::None;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <parallel_hashmap/phmap.h>
|
||||
#include "EffectInfo.h"
|
||||
#include "../ShaderEffectDesc.h"
|
||||
#include <parallel_hashmap/phmap.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
|
|
@ -20,8 +21,17 @@ public:
|
|||
|
||||
const std::vector<EffectInfo>& GetEffects() noexcept;
|
||||
|
||||
// 由于 WinUI 使用 UTF-16,这里也以 UTF-16 作为参数以减少编码转换
|
||||
const EffectInfo* GetEffect(std::wstring_view name) noexcept;
|
||||
const EffectInfo* GetEffect(std::string_view name) noexcept;
|
||||
|
||||
std::string SubmitCompileShaderEffectTask(
|
||||
std::string_view effectName,
|
||||
const phmap::flat_hash_map<std::string, float>* inlineParams,
|
||||
D3D_SHADER_MODEL shaderModel,
|
||||
bool isFP16Enabled,
|
||||
bool isAdvancedColorEnabled
|
||||
) noexcept;
|
||||
|
||||
bool GetTaskResult(std::string taskKey, const ShaderEffectDesc* &effectDesc) noexcept;
|
||||
|
||||
private:
|
||||
EffectsService() = default;
|
||||
|
|
@ -29,7 +39,15 @@ private:
|
|||
void _WaitForInitialize() noexcept;
|
||||
|
||||
std::vector<EffectInfo> _effects;
|
||||
phmap::flat_hash_map<std::wstring, uint32_t> _effectsMap;
|
||||
phmap::flat_hash_map<std::string_view, uint32_t> _effectsMap;
|
||||
|
||||
struct _ShaderEffectMemCacheItem {
|
||||
ShaderEffectDesc effectDesc;
|
||||
// UINT_MAX 表示尚未编译完成
|
||||
uint32_t lastAccess = std::numeric_limits<uint32_t>::max();
|
||||
};
|
||||
phmap::flat_hash_map<std::string, _ShaderEffectMemCacheItem> _shaderEffectCache;
|
||||
|
||||
std::atomic<bool> _initialized = false;
|
||||
bool _initializedCache = false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,13 +55,6 @@ enum class OutputAlignment {
|
|||
COUNT
|
||||
};
|
||||
|
||||
enum class EffectType {
|
||||
Shader,
|
||||
// 下面的类型未实现
|
||||
ONNX,
|
||||
Extension
|
||||
};
|
||||
|
||||
enum class ScalingType {
|
||||
Normal, // Scale 表示缩放倍数
|
||||
Fit, // Scale 表示相对于屏幕能容纳的最大等比缩放的比例
|
||||
|
|
@ -70,7 +63,6 @@ enum class ScalingType {
|
|||
};
|
||||
|
||||
struct EffectOption {
|
||||
EffectType type;
|
||||
std::string name;
|
||||
phmap::flat_hash_map<std::string, float> parameters;
|
||||
ScalingType scalingType = ScalingType::Normal;
|
||||
|
|
|
|||
|
|
@ -76,41 +76,6 @@ enum class ComponentState {
|
|||
Error
|
||||
};
|
||||
|
||||
struct Size {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
bool operator==(const Size&) const noexcept = default;
|
||||
|
||||
explicit operator SIZE() const noexcept {
|
||||
return { (LONG)width,(LONG)height };
|
||||
}
|
||||
};
|
||||
|
||||
struct Point {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
|
||||
bool operator==(const Point&) const noexcept = default;
|
||||
|
||||
explicit operator POINT() const noexcept {
|
||||
return { (LONG)x,(LONG)y };
|
||||
}
|
||||
};
|
||||
|
||||
struct Rect {
|
||||
uint32_t left;
|
||||
uint32_t top;
|
||||
uint32_t right;
|
||||
uint32_t bottom;
|
||||
|
||||
bool operator==(const Rect& other) const = default;
|
||||
|
||||
explicit operator RECT() const noexcept {
|
||||
return { (LONG)left,(LONG)top,(LONG)right,(LONG)bottom };
|
||||
}
|
||||
};
|
||||
|
||||
struct ColorInfo {
|
||||
winrt::AdvancedColorKind kind = winrt::AdvancedColorKind::StandardDynamicRange;
|
||||
// HDR 模式下最大亮度,1.0 表示 80nit
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include <ShellScalingApi.h>
|
||||
#include <ShlObj.h>
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Magpie;
|
||||
|
||||
namespace Magpie {
|
||||
|
|
@ -179,8 +178,8 @@ static HRESULT CALLBACK TaskDialogCallback(
|
|||
|
||||
static void ShowErrorMessage(const wchar_t* mainInstruction, const wchar_t* content) noexcept {
|
||||
LocalizationService& ls = LocalizationService::Get();
|
||||
const hstring errorStr = ls.GetLocalizedString(L"AppSettings_Dialog_Error");
|
||||
const hstring exitStr = ls.GetLocalizedString(L"AppSettings_Dialog_Exit");
|
||||
const winrt::hstring errorStr = ls.GetLocalizedString(L"AppSettings_Dialog_Error");
|
||||
const winrt::hstring exitStr = ls.GetLocalizedString(L"AppSettings_Dialog_Exit");
|
||||
|
||||
TASKDIALOG_BUTTON button{ IDCANCEL, exitStr.c_str() };
|
||||
TASKDIALOGCONFIG tdc{
|
||||
|
|
@ -229,8 +228,8 @@ bool AppSettings::Initialize() noexcept {
|
|||
logger.Error("读取配置文件失败");
|
||||
|
||||
LocalizationService& ls = LocalizationService::Get();
|
||||
hstring title = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ReadFailed");
|
||||
hstring content = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ConfigLocation");
|
||||
winrt::hstring title = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ReadFailed");
|
||||
winrt::hstring content = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ConfigLocation");
|
||||
ShowErrorMessage(title.c_str(),
|
||||
fmt::format(fmt::runtime(std::wstring_view(content)), existingConfigPath.native()).c_str());
|
||||
|
||||
|
|
@ -251,8 +250,8 @@ bool AppSettings::Initialize() noexcept {
|
|||
Logger::Get().Error(fmt::format("解析配置失败\n\t错误码: {}", (int)doc.GetParseError()));
|
||||
|
||||
LocalizationService& ls = LocalizationService::Get();
|
||||
hstring title = ls.GetLocalizedString(L"AppSettings_ErrorDialog_NotValidJson");
|
||||
hstring content = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ConfigLocation");
|
||||
winrt::hstring title = ls.GetLocalizedString(L"AppSettings_ErrorDialog_NotValidJson");
|
||||
winrt::hstring content = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ConfigLocation");
|
||||
ShowErrorMessage(title.c_str(),
|
||||
fmt::format(fmt::runtime(std::wstring_view(content)), existingConfigPath.native()).c_str());
|
||||
|
||||
|
|
@ -263,8 +262,8 @@ bool AppSettings::Initialize() noexcept {
|
|||
Logger::Get().Error("配置文件根元素不是 Object");
|
||||
|
||||
LocalizationService& ls = LocalizationService::Get();
|
||||
hstring title = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ParseFailed");
|
||||
hstring content = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ConfigLocation");
|
||||
winrt::hstring title = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ParseFailed");
|
||||
winrt::hstring content = ls.GetLocalizedString(L"AppSettings_ErrorDialog_ConfigLocation");
|
||||
ShowErrorMessage(title.c_str(),
|
||||
fmt::format(fmt::runtime(std::wstring_view(content)), existingConfigPath.native()).c_str());
|
||||
|
||||
|
|
@ -286,12 +285,12 @@ bool AppSettings::Save() noexcept {
|
|||
return _Save(*this);
|
||||
}
|
||||
|
||||
fire_and_forget AppSettings::SaveAsync() noexcept {
|
||||
winrt::fire_and_forget AppSettings::SaveAsync() noexcept {
|
||||
_UpdateWindowPlacement();
|
||||
|
||||
// 拷贝当前配置
|
||||
_AppSettingsData data = *this;
|
||||
co_await resume_background();
|
||||
co_await winrt::resume_background();
|
||||
|
||||
_Save(data);
|
||||
}
|
||||
|
|
@ -715,8 +714,8 @@ void AppSettings::_LoadSettings(const rapidjson::GenericObject<true, rapidjson::
|
|||
if (windowPosNode != root.MemberEnd() && windowPosNode->value.IsObject()) {
|
||||
auto windowPosObj = windowPosNode->value.GetObj();
|
||||
|
||||
Point center{};
|
||||
Size size{};
|
||||
winrt::Point center{};
|
||||
winrt::Size size{};
|
||||
if (JsonHelper::ReadFloat(windowPosObj, "centerX", center.X, true) &&
|
||||
JsonHelper::ReadFloat(windowPosObj, "centerY", center.Y, true) &&
|
||||
JsonHelper::ReadFloat(windowPosObj, "width", size.Width, true) &&
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ EffectParametersViewModel::EffectParametersViewModel(uint32_t scalingModeIdx, ui
|
|||
: _scalingModeIdx(scalingModeIdx), _effectIdx(effectIdx)
|
||||
{
|
||||
ScalingMode& scalingMode = ScalingModesService::Get().GetScalingMode(_scalingModeIdx);
|
||||
_effectInfo = EffectsService::Get().GetEffect(scalingMode.effects[_effectIdx].name);
|
||||
_effectInfo = EffectsService::Get().GetEffect(
|
||||
StrHelper::UTF16ToUTF8(scalingMode.effects[_effectIdx].name));
|
||||
|
||||
phmap::flat_hash_map<std::wstring, float>& params = _Data();
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ ScalingModeEffectItem::ScalingModeEffectItem(uint32_t scalingModeIdx, uint32_t e
|
|||
{
|
||||
EffectItem& data = _Data();
|
||||
|
||||
_effectInfo = EffectsService::Get().GetEffect(data.name);
|
||||
_effectInfo = EffectsService::Get().GetEffect(StrHelper::UTF16ToUTF8(data.name));
|
||||
|
||||
if (_effectInfo) {
|
||||
_name = EffectHelper::GetDisplayName(data.name);
|
||||
|
|
|
|||
|
|
@ -215,7 +215,8 @@ void ScalingModeItem::AddEffect(const hstring& fullName) {
|
|||
EffectItem& effect = _Data().effects.emplace_back();
|
||||
effect.name = fullName;
|
||||
|
||||
const EffectInfo* effectInfo = EffectsService::Get().GetEffect(fullName);
|
||||
const EffectInfo* effectInfo =
|
||||
EffectsService::Get().GetEffect(StrHelper::UTF16ToUTF8(fullName));
|
||||
assert(effectInfo);
|
||||
if (effectInfo->scaleFactor == 0) {
|
||||
// 支持缩放的效果默认等比缩放到充满屏幕
|
||||
|
|
@ -264,7 +265,7 @@ hstring ScalingModeItem::Description() const noexcept {
|
|||
result.append(L" > ");
|
||||
}
|
||||
|
||||
if (EffectsService::Get().GetEffect(effect.name) != nullptr) {
|
||||
if (EffectsService::Get().GetEffect(StrHelper::UTF16ToUTF8(effect.name))) {
|
||||
result += EffectHelper::GetDisplayName(effect.name);
|
||||
} else {
|
||||
result += L'(';
|
||||
|
|
@ -282,7 +283,7 @@ bool ScalingModeItem::HasUnkownEffects() const noexcept {
|
|||
}
|
||||
|
||||
for (const EffectItem& effect : _Data().effects) {
|
||||
if (!EffectsService::Get().GetEffect(effect.name)) {
|
||||
if (!EffectsService::Get().GetEffect(StrHelper::UTF16ToUTF8(effect.name))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,13 +135,15 @@ void ScalingModesPage::_BuildEffectMenu() noexcept {
|
|||
hstring name1 = unbox_value<hstring>(l.try_as<MenuFlyoutItem>().Tag());
|
||||
hstring name2 = unbox_value<hstring>(r.try_as<MenuFlyoutItem>().Tag());
|
||||
|
||||
const EffectInfo* effectInfo1 = EffectsService::Get().GetEffect(name1);
|
||||
const EffectInfo* EffectInfo = EffectsService::Get().GetEffect(name2);
|
||||
const EffectInfo* effectInfo1 =
|
||||
EffectsService::Get().GetEffect(StrHelper::UTF16ToUTF8(name1));
|
||||
const EffectInfo* effectInfo2 =
|
||||
EffectsService::Get().GetEffect(StrHelper::UTF16ToUTF8(name2));
|
||||
|
||||
const std::string& sortName1 =
|
||||
effectInfo1->sortName.empty() ? effectInfo1->name : effectInfo1->sortName;
|
||||
const std::string& sortName2 =
|
||||
EffectInfo->sortName.empty() ? EffectInfo->name : EffectInfo->sortName;
|
||||
effectInfo2->sortName.empty() ? effectInfo2->name : effectInfo2->sortName;
|
||||
|
||||
return sortName1 < sortName2;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
#include "pch.h"
|
||||
#include "AppSettings.h"
|
||||
#include "EffectHelper.h"
|
||||
#include "EffectsService.h"
|
||||
#include "JsonHelper.h"
|
||||
#include "ScalingMode.h"
|
||||
#include "ScalingModesService.h"
|
||||
#include "StrHelper.h"
|
||||
|
||||
using namespace ::Magpie;
|
||||
using namespace winrt;
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
ScalingMode& ScalingModesService::GetScalingMode(uint32_t idx) {
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ ScalingError ScalingService::_StartScaleImpl(HWND hWnd, const Profile& profile,
|
|||
return ScalingError::InvalidScalingMode;
|
||||
} else {
|
||||
for (const EffectItem& effect : effects) {
|
||||
if (!EffectsService::Get().GetEffect(effect.name)) {
|
||||
if (!EffectsService::Get().GetEffect(StrHelper::UTF16ToUTF8(effect.name))) {
|
||||
// 存在无法解析的效果
|
||||
return ScalingError::InvalidScalingMode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,4 +53,39 @@ uint32_t Measure(const Fn& func) noexcept {
|
|||
return (uint32_t)dura.count();
|
||||
}
|
||||
|
||||
struct SizeU {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
bool operator==(const SizeU&) const noexcept = default;
|
||||
|
||||
explicit operator SIZE() const noexcept {
|
||||
return { (LONG)width,(LONG)height };
|
||||
}
|
||||
};
|
||||
|
||||
struct PointU {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
|
||||
bool operator==(const PointU&) const noexcept = default;
|
||||
|
||||
explicit operator POINT() const noexcept {
|
||||
return { (LONG)x,(LONG)y };
|
||||
}
|
||||
};
|
||||
|
||||
struct RectU {
|
||||
uint32_t left;
|
||||
uint32_t top;
|
||||
uint32_t right;
|
||||
uint32_t bottom;
|
||||
|
||||
bool operator==(const RectU& other) const = default;
|
||||
|
||||
explicit operator RECT() const noexcept {
|
||||
return { (LONG)left,(LONG)top,(LONG)right,(LONG)bottom };
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue