Magpie/src/Magpie.Core/DirectXHelper.cpp
Xu a6f86d0849
FX 支持使用 FP16 (#1049)
* feat: 自动使用半精度浮点数,除非在开发者选项中禁用

* feat: 添加用于测试效果性能的模式,将持续渲染不做等待

* chore: 避免不同配置使用相同的着色器头文件

* fix: 不再使用 wil::CreateDirectoryDeepNoThrow,因为它不支持相对路径

* feat: 内联常量改为使用全局只读变量实现
这可以避免宏定义引起的名字冲突,如 #678

* feat: 引入 rapidhash,不再使用 wyhash
这会使效果缓存失效

* feat: 优化缓存系统
加载缓存将检查源码是否匹配,更改缓存文件名

* ui: 优化开发者选项 UI

* perf: 避免复制

* feat: 使用 USE_FP16 指令声明效果支持 FP16

* fix: 小修复

* chore: 修改措辞

* feat: 使几个效果支持 FP16,但性能变化不如预期

* feat: 适配几个效果供测试

* CuNNy-D16N16

* ACNet 从 mad 改为使用 dp4

* Anime4K_Upscale_L 和 CuNNy-16x16C-NVL 改为使用 mad

* ACNet 改为使用 mad

* feat: FX 支持 USE 指令

* feat: 内置函数新增 MulAdd

* perf: 优化 jinc 和 Anime4K_3D_Upscale_US

* perf: 优化 Anime4K_3D_Upscale_US 和 Anime4K_Restore_L

* perf: 优化 Anime4K_Restore_M

* perf: 优化几个效果

* perf: 优化两个效果

* perf: 优化两个效果

* perf: 优化更多效果

* perf: 优化更多效果

* perf: 优化更多效果

* feat: 记录显卡是否支持 fp16

* perf: 优化 CAS

* perf: 优化 FSRCNNX

* perf: 优化更多效果

* perf: 优化更多效果

* perf: 优化更多效果

* perf: 优化更多效果

* perf: 优化更多效果

* fix: 修正字符串资源

* fix: 修正字符串资源

* perf: 优化 FSR_EASU

* perf: 优化 FSR_RCAS

* perf: NIS 和 NVSharpen 更新到 v1.0.3
也添加了 FP16 支持,性能有很小的下降,但显存占用大幅下降

* feat: 叠加层上显示效果是否使用 FP16

* docs: 更新文档

* docs: 优化文档

* docs: 优化文档
2025-02-01 12:33:20 +08:00

110 lines
2.8 KiB
C++

#include "pch.h"
#include "DirectXHelper.h"
#include <d3dcompiler.h>
#include "Logger.h"
#include "StrHelper.h"
namespace Magpie {
bool DirectXHelper::CompileComputeShader(
std::string_view hlsl,
const char* entryPoint,
ID3DBlob** blob,
const char* sourceName,
ID3DInclude* include,
const std::vector<std::pair<std::string, std::string>>& macros,
bool warningsAreErrors
) {
winrt::com_ptr<ID3DBlob> errorMsgs = nullptr;
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_ALL_RESOURCES_BOUND;
if (warningsAreErrors) {
flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
}
#ifdef _DEBUG
flags |= D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
#else
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
#endif
std::unique_ptr<D3D_SHADER_MACRO[]> mc(new D3D_SHADER_MACRO[macros.size() + 1]);
for (UINT i = 0; i < macros.size(); ++i) {
mc[i] = { macros[i].first.c_str(), macros[i].second.c_str() };
}
mc[macros.size()] = { nullptr,nullptr };
HRESULT hr = D3DCompile(hlsl.data(), hlsl.size(), sourceName, mc.get(), include,
entryPoint, "cs_5_0", flags, 0, blob, errorMsgs.put());
if (FAILED(hr)) {
if (errorMsgs) {
Logger::Get().ComError(StrHelper::Concat("编译计算着色器失败: ", (const char*)errorMsgs->GetBufferPointer()), hr);
}
return false;
}
// 警告消息
if (errorMsgs) {
Logger::Get().Warn(StrHelper::Concat("编译计算着色器时产生警告: ", (const char*)errorMsgs->GetBufferPointer()));
}
return true;
}
bool DirectXHelper::IsDebugLayersAvailable() noexcept {
#ifdef _DEBUG
static bool result = SUCCEEDED(D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device.
nullptr,
D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers.
nullptr, // Any feature level will do.
0,
D3D11_SDK_VERSION,
nullptr, // No need to keep the D3D device reference.
nullptr, // No need to know the feature level.
nullptr // No need to keep the D3D device context reference.
));
return result;
#else
// Relaese 配置不使用调试层
return false;
#endif
}
winrt::com_ptr<ID3D11Texture2D> DirectXHelper::CreateTexture2D(
ID3D11Device* d3dDevice,
DXGI_FORMAT format,
UINT width,
UINT height,
UINT bindFlags,
D3D11_USAGE usage,
UINT miscFlags,
const D3D11_SUBRESOURCE_DATA* pInitialData
) noexcept {
const D3D11_TEXTURE2D_DESC desc{
.Width = width,
.Height = height,
.MipLevels = 1,
.ArraySize = 1,
.Format = format,
.SampleDesc{
.Count = 1,
.Quality = 0
},
.Usage = usage,
.BindFlags = bindFlags,
.MiscFlags = miscFlags
};
winrt::com_ptr<ID3D11Texture2D> result;
HRESULT hr = d3dDevice->CreateTexture2D(&desc, pInitialData, result.put());
if (FAILED(hr)) {
Logger::Get().ComError("CreateTexture2D 失败", hr);
return nullptr;
}
return result;
}
}