GS/DX12: Support SM6.5

This commit is contained in:
TheLastRar
2026-09-18 08:24:58 +02:00
committed by lightningterror
parent 7840e1bb4d
commit 72a29eeabd
8 changed files with 175 additions and 7 deletions
+1
View File
@@ -33,6 +33,7 @@
<DepsDLLs Include="$(DepsBinDir)avutil-*.dll" />
<DepsDLLs Include="$(DepsBinDir)swresample-*.dll" />
<DepsDLLs Include="$(DepsBinDir)swscale-*.dll" />
<DepsDLLs Include="$(DepsBinDir)dxcompiler.dll" />
</ItemGroup>
<ItemGroup>
<AgilityDLLs Condition="Exists('$(DepsBinDir)D3D12\D3D12Core.dll')" Include="$(DepsBinDir)D3D12\D3D12Core.dll" />
+1 -1
View File
@@ -63,7 +63,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>comctl32.lib;ws2_32.lib;shlwapi.lib;winmm.lib;rpcrt4.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>dxguid.lib;dinput8.lib;hid.lib;PowrProf.lib;d3dcompiler.lib;d3d11.lib;d3d12.lib;dxgi.lib;strmiids.lib;comsuppw.lib;OneCore.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>dxguid.lib;dinput8.lib;hid.lib;PowrProf.lib;d3dcompiler.lib;dxcompiler.lib;d3d11.lib;d3d12.lib;dxgi.lib;strmiids.lib;comsuppw.lib;OneCore.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies Condition="'$(Platform)'!='ARM64'">opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
+2 -1
View File
@@ -1186,6 +1186,7 @@ if(WIN32)
hid.lib
PowrProf.lib
d3dcompiler.lib
dxcompiler.lib
d3d11.lib
d3d12.lib
dxgi.lib
@@ -1310,7 +1311,7 @@ function(setup_main_executable target)
# Copy dependency libraries.
set(DEPS_BINDIR "${CMAKE_SOURCE_DIR}/deps/bin")
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll libwebpdemux.dll libwebpmux.dll lz4.dll SDL3.dll shaderc_shared.dll z.dll zstd.dll plutovg.dll plutosvg.dll ryml.dll)
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll libwebpdemux.dll libwebpmux.dll lz4.dll SDL3.dll shaderc_shared.dll z.dll zstd.dll plutovg.dll plutosvg.dll ryml.dll dxcompiler.dll)
set(DEPS_TO_COPY
$<IF:$<CONFIG:Debug>,kddockwidgets-qt6d.dll,kddockwidgets-qt6.dll>
${DEPS_TO_COPY}
+130 -3
View File
@@ -22,6 +22,7 @@
#include <d3d11.h>
#include <directx/d3d12.h>
#include <d3dcompiler.h>
#include <dxcapi.h>
#include <fstream>
#include "fmt/format.h"
@@ -492,18 +493,23 @@ const char* D3D::ShaderModelToCacheString(D3D::ShaderModel shader_model)
case ShaderModel::SM50:
return "sm50";
case ShaderModel::SM51:
case ShaderModel::SM60:
case ShaderModel::SM61:
case ShaderModel::SM62:
case ShaderModel::SM63:
case ShaderModel::SM64:
return "sm51";
case ShaderModel::SM65:
return "sm65";
default:
return "unk";
}
}
wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShader(D3D::ShaderType type, D3D::ShaderModel shader_model, bool debug,
wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShaderDXBC(D3D::ShaderType type, D3D::ShaderModel shader_model, bool debug,
const std::string_view code, const D3D_SHADER_MACRO* macros /* = nullptr */,
const char* entry_point /* = "main" */)
{
const GSShaderCompileIndicator::CompileTimer compile_timer;
const char* target;
switch (shader_model)
{
@@ -580,3 +586,124 @@ wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShader(D3D::ShaderType type, D3D::Sha
return blob;
}
wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShaderDXIL(D3D::ShaderType type, D3D::ShaderModel shader_model, bool debug,
const std::string_view code, const D3D_SHADER_MACRO* macros /* = nullptr */,
const char* entry_point /* = "main" */)
{
const wchar_t* target;
switch (shader_model)
{
case ShaderModel::SM60:
case ShaderModel::SM61:
case ShaderModel::SM62:
case ShaderModel::SM63:
case ShaderModel::SM64:
pxAssert(false);
break;
case ShaderModel::SM65:
default:
{
static constexpr std::array<const wchar_t*, 4> targets = {{L"vs_6_5", L"ps_6_5", L"cs_6_5"}};
target = targets[static_cast<int>(type)];
}
break;
}
// Build Args.
std::vector<std::wstring> args;
if (macros)
{
for (const D3D_SHADER_MACRO* macro = macros; macro->Name != nullptr; macro++)
args.push_back(StringUtil::UTF8StringToWideString(fmt::format("-D{}={}", macro->Name, macro->Definition)));
}
if (entry_point)
{
args.push_back(L"-E");
args.push_back(StringUtil::UTF8StringToWideString(entry_point));
}
args.push_back(L"-T");
args.push_back(target);
if (debug)
{
args.push_back(L"-Od");
args.push_back(L"-Zi");
args.push_back(L"-Zss");
args.push_back(L"-Qembed_debug");
}
else
{
args.push_back(L"-O3");
args.push_back(L"-Qstrip_reflect");
}
std::vector<const wchar_t*> arg_ptrs;
arg_ptrs.reserve(args.size());
for (const std::wstring& arg : args)
arg_ptrs.push_back(arg.c_str());
// Compile Shader.
wil::com_ptr_nothrow<IDxcCompiler3> compiler;
DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(compiler.put()));
const DxcBuffer source{code.data(), code.length(), DXC_CP_UTF8};
wil::com_ptr_nothrow<IDxcResult> results;
HRESULT hr = compiler->Compile(&source, arg_ptrs.data(), arg_ptrs.size(), nullptr, IID_PPV_ARGS(results.put()));
if (FAILED(hr))
{
Console.WriteLn("Compiler Failed");
return {};
}
wil::com_ptr_nothrow<IDxcBlobUtf8> error_string = nullptr;
results->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(error_string.put()), nullptr);
results->GetStatus(&hr);
if (FAILED(hr))
{
std::string target_utf8 = StringUtil::WideStringToUTF8String(target);
Console.WriteLn("D3D: Failed to compile '%s':\n%s", target_utf8.c_str(), error_string->GetStringPointer());
std::ofstream ofs(Path::Combine(EmuFolders::Logs, fmt::format("pcsx2_bad_shader_{}.txt", s_next_bad_shader_id++)),
std::ofstream::out | std::ofstream::binary);
if (ofs.is_open())
{
ofs << code;
ofs << "\n\nCompile as " << target_utf8.c_str() << " failed: " << hr << "\n";
ofs.write(error_string->GetStringPointer(), error_string->GetStringLength());
ofs << "\n";
if (macros)
{
for (const D3D_SHADER_MACRO* macro = macros; macro->Name != nullptr; macro++)
ofs << "#define " << macro->Name << " " << macro->Definition << "\n";
}
ofs.close();
}
return {};
}
if (error_string->GetStringLength() != 0)
Console.Warning("'%s' compiled with warnings:\n%s", StringUtil::WideStringToUTF8String(target).c_str(), error_string->GetStringPointer());
wil::com_ptr_nothrow<ID3DBlob> blob = nullptr;
results->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(blob.put()), nullptr);
return blob;
}
wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShader(D3D::ShaderType type, D3D::ShaderModel shader_model, bool debug,
const std::string_view code, const D3D_SHADER_MACRO* macros /* = nullptr */,
const char* entry_point /* = "main" */)
{
const GSShaderCompileIndicator::CompileTimer compile_timer;
if (static_cast<int>(shader_model) < 0x65)
return CompileShaderDXBC(type, shader_model, debug, code, macros, entry_point);
else
return CompileShaderDXIL(type, shader_model, debug, code, macros, entry_point);
}
+11
View File
@@ -69,10 +69,21 @@ namespace D3D
SM41 = 0x41, // DX11 FL 10_1
SM50 = 0x50, // DX11 FL 11_0
SM51 = 0x51, // DX12
SM60 = 0x60,
SM61 = 0x61,
SM62 = 0x62,
SM63 = 0x63,
SM64 = 0x64,
SM65 = 0x65,
};
const char* ShaderModelToCacheString(ShaderModel shader_model);
wil::com_ptr_nothrow<ID3DBlob> CompileShader(ShaderType type, ShaderModel shader_model, bool debug,
const std::string_view code, const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
wil::com_ptr_nothrow<ID3DBlob> CompileShaderDXBC(ShaderType type, ShaderModel shader_model, bool debug,
const std::string_view code, const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
wil::com_ptr_nothrow<ID3DBlob> CompileShaderDXIL(ShaderType type, ShaderModel shader_model, bool debug,
const std::string_view code, const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
}; // namespace D3D
@@ -56,7 +56,6 @@ bool D3D12ShaderCache::CacheIndexKey::operator!=(const CacheIndexKey& key) const
bool D3D12ShaderCache::Open(D3D::ShaderModel shader_model, bool debug)
{
// Only support SM5.1 for now, which is the minimum for D3D12.
pxAssert(shader_model >= D3D::ShaderModel::SM51);
m_shader_model = shader_model;
m_debug = debug;
+27 -1
View File
@@ -152,6 +152,29 @@ bool GSDevice12::SupportsProgrammableSamplePositions()
return false;
}
D3D_SHADER_MODEL GSDevice12::DetectShaderModelSupport() {
// CheckFeatureSupport will fail if the runtime dosen't support a requested shader model.
// Loop though ranges of valid shader models until the check succeeds.
constexpr std::array<std::array<D3D_SHADER_MODEL, 2>, 2> shader_model_ranges{{
{D3D_SHADER_MODEL_6_5, D3D_SHADER_MODEL_6_0},
{D3D_SHADER_MODEL_5_1, D3D_SHADER_MODEL_5_1},
}};
for (const std::array<D3D_SHADER_MODEL, 2>& range : shader_model_ranges)
{
for (int i = range[0]; i >= range[1]; i--)
{
D3D12_FEATURE_DATA_SHADER_MODEL shader_model_device = {static_cast<D3D_SHADER_MODEL>(i)};
const HRESULT hr = m_device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shader_model_device, sizeof(shader_model_device));
if (SUCCEEDED(hr))
return shader_model_device.HighestShaderModel;
}
}
// If the above somehow fails.
return D3D_SHADER_MODEL_5_1;
}
u32 GSDevice12::GetAdapterVendorID() const
{
if (!m_adapter)
@@ -992,7 +1015,7 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
m_tfx_source = std::move(*shader);
}
if (!m_shader_cache.Open(D3D::ShaderModel::SM51, GSConfig.UseDebugDevice))
if (!m_shader_cache.Open(static_cast<D3D::ShaderModel>(m_shader_model), GSConfig.UseDebugDevice))
Console.Warning("D3D12: Shader cache failed to open.");
if (!CreateRootSignatures())
@@ -1538,6 +1561,9 @@ bool GSDevice12::CheckFeatures(const u32& vendor_id)
DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing_supported, sizeof(allow_tearing_supported));
m_allow_tearing_supported = (SUCCEEDED(hr) && allow_tearing_supported == TRUE);
m_shader_model = DetectShaderModelSupport();
Console.WriteLnFmt("D3D12: Shader Model: {}.{}", (m_shader_model & 0xF0) >> 4, (m_shader_model & 0xF));
D3D12_FEATURE_DATA_ARCHITECTURE1 device_architecture1 = {};
hr = m_device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE1, &device_architecture1, sizeof(device_architecture1));
m_uma = SUCCEEDED(hr) && device_architecture1.UMA;
+3
View File
@@ -158,6 +158,8 @@ public:
// Partial depth copies require ProgrammableSamplePositions tier 1.
bool SupportsProgrammableSamplePositions();
D3D_SHADER_MODEL DetectShaderModelSupport();
enum class WaitType
{
None, ///< Don't wait (async)
@@ -380,6 +382,7 @@ private:
bool m_allow_tearing_supported = false;
bool m_using_allow_tearing = false;
bool m_is_exclusive_fullscreen = false;
D3D_SHADER_MODEL m_shader_model = D3D_SHADER_MODEL_5_1;
bool m_uma = false;
bool m_typed_casting_supported = false;
bool m_enhanced_barriers = false;