mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 15:49:25 +01:00
Add D3DCommon (shared code between D3D11 and D3D12)
This commit is contained in:
parent
f6641b7e4f
commit
ea15080d8f
@ -4,6 +4,7 @@ add_subdirectory(Software)
|
|||||||
add_subdirectory(Vulkan)
|
add_subdirectory(Vulkan)
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
add_subdirectory(D3DCommon)
|
||||||
add_subdirectory(D3D)
|
add_subdirectory(D3D)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
15
Source/Core/VideoBackends/D3DCommon/CMakeLists.txt
Normal file
15
Source/Core/VideoBackends/D3DCommon/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
add_library(videod3dcommon
|
||||||
|
Common.cpp
|
||||||
|
Common.h
|
||||||
|
Shader.cpp
|
||||||
|
Shader.h
|
||||||
|
SwapChain.cpp
|
||||||
|
SwapChain.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(videod3dcommon
|
||||||
|
PUBLIC
|
||||||
|
common
|
||||||
|
videocommon
|
||||||
|
videod3dcommon
|
||||||
|
)
|
320
Source/Core/VideoBackends/D3DCommon/Common.cpp
Normal file
320
Source/Core/VideoBackends/D3DCommon/Common.cpp
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
// Copyright 2019 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <d3d12.h>
|
||||||
|
#include <dxgi1_3.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/DynamicLibrary.h"
|
||||||
|
#include "Common/MsgHandler.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
#include "VideoBackends/D3DCommon/Common.h"
|
||||||
|
#include "VideoCommon/TextureConfig.h"
|
||||||
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
|
namespace D3DCommon
|
||||||
|
{
|
||||||
|
pD3DCompile d3d_compile;
|
||||||
|
|
||||||
|
static Common::DynamicLibrary s_dxgi_library;
|
||||||
|
static Common::DynamicLibrary s_d3dcompiler_library;
|
||||||
|
static bool s_libraries_loaded = false;
|
||||||
|
|
||||||
|
static HRESULT (*create_dxgi_factory)(REFIID riid, _COM_Outptr_ void** ppFactory);
|
||||||
|
static HRESULT (*create_dxgi_factory2)(UINT Flags, REFIID riid, void** ppFactory);
|
||||||
|
|
||||||
|
bool LoadLibraries()
|
||||||
|
{
|
||||||
|
if (s_libraries_loaded)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!s_dxgi_library.Open("dxgi.dll"))
|
||||||
|
{
|
||||||
|
PanicAlertT("Failed to load dxgi.dll");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_d3dcompiler_library.Open(D3DCOMPILER_DLL_A))
|
||||||
|
{
|
||||||
|
PanicAlertT("Failed to load %s. If you are using Windows 7, try installing the "
|
||||||
|
"KB4019990 update package.",
|
||||||
|
D3DCOMPILER_DLL_A);
|
||||||
|
s_dxgi_library.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required symbols.
|
||||||
|
if (!s_d3dcompiler_library.GetSymbol("D3DCompile", &d3d_compile) ||
|
||||||
|
!s_dxgi_library.GetSymbol("CreateDXGIFactory", &create_dxgi_factory))
|
||||||
|
{
|
||||||
|
PanicAlertT("Failed to find one or more D3D symbols");
|
||||||
|
s_d3dcompiler_library.Close();
|
||||||
|
s_dxgi_library.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional symbols.
|
||||||
|
s_dxgi_library.GetSymbol("CreateDXGIFactory2", &create_dxgi_factory2);
|
||||||
|
s_libraries_loaded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadLibraries()
|
||||||
|
{
|
||||||
|
create_dxgi_factory = nullptr;
|
||||||
|
create_dxgi_factory2 = nullptr;
|
||||||
|
d3d_compile = nullptr;
|
||||||
|
s_d3dcompiler_library.Close();
|
||||||
|
s_dxgi_library.Close();
|
||||||
|
s_libraries_loaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDXGIFactory2* CreateDXGIFactory(bool debug_device)
|
||||||
|
{
|
||||||
|
IDXGIFactory2* factory;
|
||||||
|
|
||||||
|
// Use Win8.1 version if available.
|
||||||
|
if (create_dxgi_factory2 &&
|
||||||
|
SUCCEEDED(create_dxgi_factory2(debug_device ? DXGI_CREATE_FACTORY_DEBUG : 0,
|
||||||
|
IID_PPV_ARGS(&factory))))
|
||||||
|
{
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to original version, without debug support.
|
||||||
|
HRESULT hr = create_dxgi_factory(IID_PPV_ARGS(&factory));
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
PanicAlert("CreateDXGIFactory() failed with HRESULT %08X", hr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetAdapterNames()
|
||||||
|
{
|
||||||
|
Microsoft::WRL::ComPtr<IDXGIFactory> factory;
|
||||||
|
HRESULT hr = create_dxgi_factory(IID_PPV_ARGS(&factory));
|
||||||
|
if (!SUCCEEDED(hr))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::vector<std::string> adapters;
|
||||||
|
IDXGIAdapter* adapter;
|
||||||
|
while (factory->EnumAdapters(static_cast<UINT>(adapters.size()), &adapter) !=
|
||||||
|
DXGI_ERROR_NOT_FOUND)
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
DXGI_ADAPTER_DESC desc;
|
||||||
|
if (SUCCEEDED(adapter->GetDesc(&desc)))
|
||||||
|
name = UTF16ToUTF8(desc.Description);
|
||||||
|
|
||||||
|
adapters.push_back(std::move(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return adapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_FORMAT GetDXGIFormatForAbstractFormat(AbstractTextureFormat format, bool typeless)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case AbstractTextureFormat::DXT1:
|
||||||
|
return DXGI_FORMAT_BC1_UNORM;
|
||||||
|
case AbstractTextureFormat::DXT3:
|
||||||
|
return DXGI_FORMAT_BC2_UNORM;
|
||||||
|
case AbstractTextureFormat::DXT5:
|
||||||
|
return DXGI_FORMAT_BC3_UNORM;
|
||||||
|
case AbstractTextureFormat::BPTC:
|
||||||
|
return DXGI_FORMAT_BC7_UNORM;
|
||||||
|
case AbstractTextureFormat::RGBA8:
|
||||||
|
return typeless ? DXGI_FORMAT_R8G8B8A8_TYPELESS : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
case AbstractTextureFormat::BGRA8:
|
||||||
|
return typeless ? DXGI_FORMAT_B8G8R8A8_TYPELESS : DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
case AbstractTextureFormat::R16:
|
||||||
|
return typeless ? DXGI_FORMAT_R16_TYPELESS : DXGI_FORMAT_R16_UNORM;
|
||||||
|
case AbstractTextureFormat::R32F:
|
||||||
|
return typeless ? DXGI_FORMAT_R32_TYPELESS : DXGI_FORMAT_R32_FLOAT;
|
||||||
|
case AbstractTextureFormat::D16:
|
||||||
|
return DXGI_FORMAT_R16_TYPELESS;
|
||||||
|
case AbstractTextureFormat::D24_S8:
|
||||||
|
return DXGI_FORMAT_R24G8_TYPELESS;
|
||||||
|
case AbstractTextureFormat::D32F:
|
||||||
|
return DXGI_FORMAT_R32_TYPELESS;
|
||||||
|
case AbstractTextureFormat::D32F_S8:
|
||||||
|
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||||
|
default:
|
||||||
|
PanicAlert("Unhandled texture format.");
|
||||||
|
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DXGI_FORMAT GetSRVFormatForAbstractFormat(AbstractTextureFormat format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case AbstractTextureFormat::DXT1:
|
||||||
|
return DXGI_FORMAT_BC1_UNORM;
|
||||||
|
case AbstractTextureFormat::DXT3:
|
||||||
|
return DXGI_FORMAT_BC2_UNORM;
|
||||||
|
case AbstractTextureFormat::DXT5:
|
||||||
|
return DXGI_FORMAT_BC3_UNORM;
|
||||||
|
case AbstractTextureFormat::BPTC:
|
||||||
|
return DXGI_FORMAT_BC7_UNORM;
|
||||||
|
case AbstractTextureFormat::RGBA8:
|
||||||
|
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
case AbstractTextureFormat::BGRA8:
|
||||||
|
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
case AbstractTextureFormat::R16:
|
||||||
|
return DXGI_FORMAT_R16_UNORM;
|
||||||
|
case AbstractTextureFormat::R32F:
|
||||||
|
return DXGI_FORMAT_R32_FLOAT;
|
||||||
|
case AbstractTextureFormat::D16:
|
||||||
|
return DXGI_FORMAT_R16_UNORM;
|
||||||
|
case AbstractTextureFormat::D24_S8:
|
||||||
|
return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||||
|
case AbstractTextureFormat::D32F:
|
||||||
|
return DXGI_FORMAT_R32_FLOAT;
|
||||||
|
case AbstractTextureFormat::D32F_S8:
|
||||||
|
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||||
|
default:
|
||||||
|
PanicAlert("Unhandled SRV format");
|
||||||
|
return DXGI_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_FORMAT GetRTVFormatForAbstractFormat(AbstractTextureFormat format, bool integer)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case AbstractTextureFormat::RGBA8:
|
||||||
|
return integer ? DXGI_FORMAT_R8G8B8A8_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
case AbstractTextureFormat::BGRA8:
|
||||||
|
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
case AbstractTextureFormat::R16:
|
||||||
|
return integer ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R16_UNORM;
|
||||||
|
case AbstractTextureFormat::R32F:
|
||||||
|
return DXGI_FORMAT_R32_FLOAT;
|
||||||
|
default:
|
||||||
|
PanicAlert("Unhandled RTV format");
|
||||||
|
return DXGI_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DXGI_FORMAT GetDSVFormatForAbstractFormat(AbstractTextureFormat format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case AbstractTextureFormat::D16:
|
||||||
|
return DXGI_FORMAT_D16_UNORM;
|
||||||
|
case AbstractTextureFormat::D24_S8:
|
||||||
|
return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
case AbstractTextureFormat::D32F:
|
||||||
|
return DXGI_FORMAT_D32_FLOAT;
|
||||||
|
case AbstractTextureFormat::D32F_S8:
|
||||||
|
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||||
|
default:
|
||||||
|
PanicAlert("Unhandled DSV format");
|
||||||
|
return DXGI_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractTextureFormat GetAbstractFormatForDXGIFormat(DXGI_FORMAT format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UINT:
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
|
||||||
|
return AbstractTextureFormat::RGBA8;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
|
||||||
|
return AbstractTextureFormat::BGRA8;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_R16_UINT:
|
||||||
|
case DXGI_FORMAT_R16_UNORM:
|
||||||
|
case DXGI_FORMAT_R16_TYPELESS:
|
||||||
|
return AbstractTextureFormat::R16;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_R32_FLOAT:
|
||||||
|
case DXGI_FORMAT_R32_TYPELESS:
|
||||||
|
return AbstractTextureFormat::R32F;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_D16_UNORM:
|
||||||
|
return AbstractTextureFormat::D16;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
||||||
|
return AbstractTextureFormat::D24_S8;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_D32_FLOAT:
|
||||||
|
return AbstractTextureFormat::D32F;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
||||||
|
return AbstractTextureFormat::D32F_S8;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC1_UNORM:
|
||||||
|
return AbstractTextureFormat::DXT1;
|
||||||
|
case DXGI_FORMAT_BC2_UNORM:
|
||||||
|
return AbstractTextureFormat::DXT3;
|
||||||
|
case DXGI_FORMAT_BC3_UNORM:
|
||||||
|
return AbstractTextureFormat::DXT5;
|
||||||
|
case DXGI_FORMAT_BC7_UNORM:
|
||||||
|
return AbstractTextureFormat::BPTC;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return AbstractTextureFormat::Undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDebugObjectName(IUnknown* resource, const char* format, ...)
|
||||||
|
{
|
||||||
|
if (!g_ActiveConfig.bEnableValidationLayer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
std::string name = StringFromFormatV(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11DeviceChild> child11;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D12DeviceChild> child12;
|
||||||
|
if (SUCCEEDED(resource->QueryInterface(IID_PPV_ARGS(&child11))))
|
||||||
|
{
|
||||||
|
child11->SetPrivateData(WKPDID_D3DDebugObjectName, static_cast<UINT>(name.length()),
|
||||||
|
name.c_str());
|
||||||
|
}
|
||||||
|
else if (SUCCEEDED(resource->QueryInterface(IID_PPV_ARGS(&child12))))
|
||||||
|
{
|
||||||
|
child12->SetPrivateData(WKPDID_D3DDebugObjectName, static_cast<UINT>(name.length()),
|
||||||
|
name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetDebugObjectName(IUnknown* resource)
|
||||||
|
{
|
||||||
|
if (!g_ActiveConfig.bEnableValidationLayer)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
UINT size = 0;
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11DeviceChild> child11;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D12DeviceChild> child12;
|
||||||
|
if (SUCCEEDED(resource->QueryInterface(IID_PPV_ARGS(&child11))))
|
||||||
|
{
|
||||||
|
child11->GetPrivateData(WKPDID_D3DDebugObjectName, &size, nullptr);
|
||||||
|
name.resize(size);
|
||||||
|
child11->GetPrivateData(WKPDID_D3DDebugObjectName, &size, name.data());
|
||||||
|
}
|
||||||
|
else if (SUCCEEDED(resource->QueryInterface(IID_PPV_ARGS(&child12))))
|
||||||
|
{
|
||||||
|
child12->GetPrivateData(WKPDID_D3DDebugObjectName, &size, nullptr);
|
||||||
|
name.resize(size);
|
||||||
|
child12->GetPrivateData(WKPDID_D3DDebugObjectName, &size, name.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
} // namespace D3DCommon
|
46
Source/Core/VideoBackends/D3DCommon/Common.h
Normal file
46
Source/Core/VideoBackends/D3DCommon/Common.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2019 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <d3dcompiler.h>
|
||||||
|
#include <dxgiformat.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "VideoCommon/VideoCommon.h"
|
||||||
|
|
||||||
|
struct IDXGIFactory2;
|
||||||
|
|
||||||
|
enum class AbstractTextureFormat : u32;
|
||||||
|
|
||||||
|
namespace D3DCommon
|
||||||
|
{
|
||||||
|
// Loading dxgi.dll and d3dcompiler.dll
|
||||||
|
bool LoadLibraries();
|
||||||
|
void UnloadLibraries();
|
||||||
|
|
||||||
|
// Returns a list of D3D device names.
|
||||||
|
std::vector<std::string> GetAdapterNames();
|
||||||
|
|
||||||
|
// Helper function which creates a DXGI factory.
|
||||||
|
IDXGIFactory2* CreateDXGIFactory(bool debug_device);
|
||||||
|
|
||||||
|
// Globally-accessible D3DCompiler function.
|
||||||
|
extern pD3DCompile d3d_compile;
|
||||||
|
|
||||||
|
// Helpers for texture format conversion.
|
||||||
|
DXGI_FORMAT GetDXGIFormatForAbstractFormat(AbstractTextureFormat format, bool typeless);
|
||||||
|
DXGI_FORMAT GetSRVFormatForAbstractFormat(AbstractTextureFormat format);
|
||||||
|
DXGI_FORMAT GetRTVFormatForAbstractFormat(AbstractTextureFormat format, bool integer);
|
||||||
|
DXGI_FORMAT GetDSVFormatForAbstractFormat(AbstractTextureFormat format);
|
||||||
|
AbstractTextureFormat GetAbstractFormatForDXGIFormat(DXGI_FORMAT format);
|
||||||
|
|
||||||
|
// This function will assign a name to the given resource.
|
||||||
|
// The DirectX debug layer will make it easier to identify resources that way,
|
||||||
|
// e.g. when listing up all resources who have unreleased references.
|
||||||
|
void SetDebugObjectName(IUnknown* resource, const char* format, ...);
|
||||||
|
std::string GetDebugObjectName(IUnknown* resource);
|
||||||
|
} // namespace D3DCommon
|
68
Source/Core/VideoBackends/D3DCommon/D3DCommon.vcxproj
Normal file
68
Source/Core/VideoBackends/D3DCommon/D3DCommon.vcxproj
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{DEA96CF2-F237-4A1A-B32F-C916769EFB50}</ProjectGuid>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\..\..\VSProps\Base.props" />
|
||||||
|
<Import Project="..\..\..\VSProps\PCHUse.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<ForcedIncludeFiles />
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<ForcedIncludeFiles />
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Common.cpp" />
|
||||||
|
<ClCompile Include="Shader.cpp" />
|
||||||
|
<ClCompile Include="SwapChain.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Common.h" />
|
||||||
|
<ClInclude Include="Shader.h" />
|
||||||
|
<ClInclude Include="SwapChain.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="$(CoreDir)VideoCommon\VideoCommon.vcxproj">
|
||||||
|
<Project>{3de9ee35-3e91-4f27-a014-2866ad8c3fe3}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="SwapChain.cpp" />
|
||||||
|
<ClCompile Include="Common.cpp" />
|
||||||
|
<ClCompile Include="Shader.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="SwapChain.h" />
|
||||||
|
<ClInclude Include="Common.h" />
|
||||||
|
<ClInclude Include="Shader.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
145
Source/Core/VideoBackends/D3DCommon/Shader.cpp
Normal file
145
Source/Core/VideoBackends/D3DCommon/Shader.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
// Copyright 2019 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Common/MsgHandler.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
#include "VideoBackends/D3DCommon/Shader.h"
|
||||||
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
|
namespace D3DCommon
|
||||||
|
{
|
||||||
|
Shader::Shader(ShaderStage stage, BinaryData bytecode)
|
||||||
|
: AbstractShader(stage), m_bytecode(std::move(bytecode))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::~Shader() = default;
|
||||||
|
|
||||||
|
bool Shader::HasBinary() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractShader::BinaryData Shader::GetBinary() const
|
||||||
|
{
|
||||||
|
return m_bytecode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* GetCompileTarget(D3D_FEATURE_LEVEL feature_level, ShaderStage stage)
|
||||||
|
{
|
||||||
|
switch (stage)
|
||||||
|
{
|
||||||
|
case ShaderStage::Vertex:
|
||||||
|
{
|
||||||
|
switch (feature_level)
|
||||||
|
{
|
||||||
|
case D3D_FEATURE_LEVEL_10_0:
|
||||||
|
return "vs_4_0";
|
||||||
|
case D3D_FEATURE_LEVEL_10_1:
|
||||||
|
return "vs_4_1";
|
||||||
|
default:
|
||||||
|
return "vs_5_0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderStage::Geometry:
|
||||||
|
{
|
||||||
|
switch (feature_level)
|
||||||
|
{
|
||||||
|
case D3D_FEATURE_LEVEL_10_0:
|
||||||
|
return "gs_4_0";
|
||||||
|
case D3D_FEATURE_LEVEL_10_1:
|
||||||
|
return "gs_4_1";
|
||||||
|
default:
|
||||||
|
return "gs_5_0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderStage::Pixel:
|
||||||
|
{
|
||||||
|
switch (feature_level)
|
||||||
|
{
|
||||||
|
case D3D_FEATURE_LEVEL_10_0:
|
||||||
|
return "ps_4_0";
|
||||||
|
case D3D_FEATURE_LEVEL_10_1:
|
||||||
|
return "ps_4_1";
|
||||||
|
default:
|
||||||
|
return "ps_5_0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderStage::Compute:
|
||||||
|
{
|
||||||
|
switch (feature_level)
|
||||||
|
{
|
||||||
|
case D3D_FEATURE_LEVEL_10_0:
|
||||||
|
case D3D_FEATURE_LEVEL_10_1:
|
||||||
|
return "";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "cs_5_0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shader::CompileShader(D3D_FEATURE_LEVEL feature_level, BinaryData* out_bytecode,
|
||||||
|
ShaderStage stage, const char* source, size_t length)
|
||||||
|
{
|
||||||
|
static constexpr D3D_SHADER_MACRO macros[] = {{"API_D3D", "1"}, {nullptr, nullptr}};
|
||||||
|
const UINT flags = g_ActiveConfig.bEnableValidationLayer ?
|
||||||
|
(D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION) :
|
||||||
|
(D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_SKIP_VALIDATION);
|
||||||
|
const char* target = GetCompileTarget(feature_level, stage);
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<ID3DBlob> code;
|
||||||
|
Microsoft::WRL::ComPtr<ID3DBlob> errors;
|
||||||
|
HRESULT hr = d3d_compile(source, length, nullptr, macros, nullptr, "main", target, flags, 0,
|
||||||
|
&code, &errors);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
static int num_failures = 0;
|
||||||
|
std::string filename = StringFromFormat(
|
||||||
|
"%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), target, num_failures++);
|
||||||
|
std::ofstream file;
|
||||||
|
File::OpenFStream(file, filename, std::ios_base::out);
|
||||||
|
file.write(source, length);
|
||||||
|
file << "\n";
|
||||||
|
file.write(static_cast<const char*>(errors->GetBufferPointer()), errors->GetBufferSize());
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
PanicAlert("Failed to compile %s:\nDebug info (%s):\n%s", filename.c_str(), target,
|
||||||
|
static_cast<const char*>(errors->GetBufferPointer()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors && errors->GetBufferSize() > 0)
|
||||||
|
{
|
||||||
|
WARN_LOG(VIDEO, "%s compilation succeeded with warnings:\n%s", target,
|
||||||
|
static_cast<const char*>(errors->GetBufferPointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
out_bytecode->resize(code->GetBufferSize());
|
||||||
|
std::memcpy(out_bytecode->data(), code->GetBufferPointer(), code->GetBufferSize());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractShader::BinaryData Shader::CreateByteCode(const void* data, size_t length)
|
||||||
|
{
|
||||||
|
BinaryData bytecode(length);
|
||||||
|
std::memcpy(bytecode.data(), data, length);
|
||||||
|
return bytecode;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace D3DCommon
|
33
Source/Core/VideoBackends/D3DCommon/Shader.h
Normal file
33
Source/Core/VideoBackends/D3DCommon/Shader.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2019 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
#include "VideoBackends/D3DCommon/Common.h"
|
||||||
|
#include "VideoCommon/AbstractShader.h"
|
||||||
|
|
||||||
|
namespace D3DCommon
|
||||||
|
{
|
||||||
|
class Shader : public AbstractShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Shader() override;
|
||||||
|
|
||||||
|
const BinaryData& GetByteCode() const { return m_bytecode; }
|
||||||
|
|
||||||
|
bool HasBinary() const override;
|
||||||
|
BinaryData GetBinary() const override;
|
||||||
|
|
||||||
|
static bool CompileShader(D3D_FEATURE_LEVEL feature_level, BinaryData* out_bytecode,
|
||||||
|
ShaderStage stage, const char* source, size_t length);
|
||||||
|
|
||||||
|
static BinaryData CreateByteCode(const void* data, size_t length);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Shader(ShaderStage stage, BinaryData bytecode);
|
||||||
|
|
||||||
|
BinaryData m_bytecode;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace D3DCommon
|
232
Source/Core/VideoBackends/D3DCommon/SwapChain.cpp
Normal file
232
Source/Core/VideoBackends/D3DCommon/SwapChain.cpp
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
// Copyright 2019 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "VideoBackends/D3DCommon/SwapChain.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/CommonFuncs.h"
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Common/MsgHandler.h"
|
||||||
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
|
static bool IsTearingSupported(IDXGIFactory2* dxgi_factory)
|
||||||
|
{
|
||||||
|
Microsoft::WRL::ComPtr<IDXGIFactory5> factory5;
|
||||||
|
if (FAILED(dxgi_factory->QueryInterface(IID_PPV_ARGS(&factory5))))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UINT allow_tearing = 0;
|
||||||
|
return SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing,
|
||||||
|
sizeof(allow_tearing))) &&
|
||||||
|
allow_tearing != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool GetFullscreenState(IDXGISwapChain1* swap_chain)
|
||||||
|
{
|
||||||
|
BOOL fs = FALSE;
|
||||||
|
return SUCCEEDED(swap_chain->GetFullscreenState(&fs, nullptr)) && fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace D3DCommon
|
||||||
|
{
|
||||||
|
SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, IUnknown* d3d_device)
|
||||||
|
: m_wsi(wsi), m_dxgi_factory(dxgi_factory), m_d3d_device(d3d_device),
|
||||||
|
m_allow_tearing_supported(IsTearingSupported(dxgi_factory))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapChain::~SwapChain()
|
||||||
|
{
|
||||||
|
// Can't destroy swap chain while it's fullscreen.
|
||||||
|
if (m_swap_chain && GetFullscreenState(m_swap_chain.Get()))
|
||||||
|
m_swap_chain->SetFullscreenState(FALSE, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwapChain::WantsStereo()
|
||||||
|
{
|
||||||
|
return g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SwapChain::GetSwapChainFlags() const
|
||||||
|
{
|
||||||
|
// This flag is necessary if we want to use a flip-model swapchain without locking the framerate
|
||||||
|
return m_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwapChain::CreateSwapChain(bool stereo)
|
||||||
|
{
|
||||||
|
RECT client_rc;
|
||||||
|
if (GetClientRect(static_cast<HWND>(m_wsi.render_surface), &client_rc))
|
||||||
|
{
|
||||||
|
m_width = client_rc.right - client_rc.left;
|
||||||
|
m_height = client_rc.bottom - client_rc.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
|
||||||
|
swap_chain_desc.Width = m_width;
|
||||||
|
swap_chain_desc.Height = m_height;
|
||||||
|
swap_chain_desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT;
|
||||||
|
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
swap_chain_desc.SampleDesc.Count = 1;
|
||||||
|
swap_chain_desc.SampleDesc.Quality = 0;
|
||||||
|
swap_chain_desc.Format = GetDXGIFormatForAbstractFormat(m_texture_format, false);
|
||||||
|
swap_chain_desc.Scaling = DXGI_SCALING_STRETCH;
|
||||||
|
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
|
swap_chain_desc.Stereo = stereo;
|
||||||
|
swap_chain_desc.Flags = GetSwapChainFlags();
|
||||||
|
|
||||||
|
HRESULT hr = m_dxgi_factory->CreateSwapChainForHwnd(
|
||||||
|
m_d3d_device.Get(), static_cast<HWND>(m_wsi.render_surface), &swap_chain_desc, nullptr,
|
||||||
|
nullptr, &m_swap_chain);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
// Flip-model discard swapchains aren't supported on Windows 8, so here we fall back to
|
||||||
|
// a sequential swapchain
|
||||||
|
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||||
|
hr = m_dxgi_factory->CreateSwapChainForHwnd(m_d3d_device.Get(),
|
||||||
|
static_cast<HWND>(m_wsi.render_surface),
|
||||||
|
&swap_chain_desc, nullptr, nullptr, &m_swap_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
// Flip-model swapchains aren't supported on Windows 7, so here we fall back to a legacy
|
||||||
|
// BitBlt-model swapchain
|
||||||
|
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
hr = m_dxgi_factory->CreateSwapChainForHwnd(m_d3d_device.Get(),
|
||||||
|
static_cast<HWND>(m_wsi.render_surface),
|
||||||
|
&swap_chain_desc, nullptr, nullptr, &m_swap_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
PanicAlert("Failed to create swap chain with HRESULT %08X", hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We handle fullscreen ourselves.
|
||||||
|
hr = m_dxgi_factory->MakeWindowAssociation(static_cast<HWND>(m_wsi.render_surface),
|
||||||
|
DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
if (FAILED(hr))
|
||||||
|
WARN_LOG(VIDEO, "MakeWindowAssociation() failed with HRESULT %08X", hr);
|
||||||
|
|
||||||
|
m_stereo = stereo;
|
||||||
|
if (!CreateSwapChainBuffers())
|
||||||
|
{
|
||||||
|
PanicAlert("Failed to create swap chain buffers");
|
||||||
|
DestroySwapChainBuffers();
|
||||||
|
m_swap_chain.Reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapChain::DestroySwapChain()
|
||||||
|
{
|
||||||
|
DestroySwapChainBuffers();
|
||||||
|
|
||||||
|
// Can't destroy swap chain while it's fullscreen.
|
||||||
|
if (m_swap_chain && GetFullscreenState(m_swap_chain.Get()))
|
||||||
|
m_swap_chain->SetFullscreenState(FALSE, nullptr);
|
||||||
|
|
||||||
|
m_swap_chain.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwapChain::ResizeSwapChain()
|
||||||
|
{
|
||||||
|
DestroySwapChainBuffers();
|
||||||
|
|
||||||
|
HRESULT hr = m_swap_chain->ResizeBuffers(SWAP_CHAIN_BUFFER_COUNT, 0, 0,
|
||||||
|
GetDXGIFormatForAbstractFormat(m_texture_format, false),
|
||||||
|
GetSwapChainFlags());
|
||||||
|
if (FAILED(hr))
|
||||||
|
WARN_LOG(VIDEO, "ResizeBuffers() failed with HRESULT %08X", hr);
|
||||||
|
|
||||||
|
DXGI_SWAP_CHAIN_DESC1 desc;
|
||||||
|
if (SUCCEEDED(m_swap_chain->GetDesc1(&desc)))
|
||||||
|
{
|
||||||
|
m_width = desc.Width;
|
||||||
|
m_height = desc.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateSwapChainBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapChain::SetStereo(bool stereo)
|
||||||
|
{
|
||||||
|
if (m_stereo == stereo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DestroySwapChain();
|
||||||
|
if (!CreateSwapChain(stereo))
|
||||||
|
{
|
||||||
|
PanicAlert("Failed to switch swap chain stereo mode");
|
||||||
|
CreateSwapChain(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwapChain::GetFullscreen() const
|
||||||
|
{
|
||||||
|
return GetFullscreenState(m_swap_chain.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapChain::SetFullscreen(bool request)
|
||||||
|
{
|
||||||
|
m_swap_chain->SetFullscreenState(request, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwapChain::CheckForFullscreenChange()
|
||||||
|
{
|
||||||
|
if (m_fullscreen_request != m_has_fullscreen)
|
||||||
|
{
|
||||||
|
HRESULT hr = m_swap_chain->SetFullscreenState(m_fullscreen_request, nullptr);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
m_has_fullscreen = m_fullscreen_request;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool new_fullscreen_state = GetFullscreenState(m_swap_chain.Get());
|
||||||
|
if (new_fullscreen_state != m_has_fullscreen)
|
||||||
|
{
|
||||||
|
m_has_fullscreen = new_fullscreen_state;
|
||||||
|
m_fullscreen_request = new_fullscreen_state;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwapChain::Present()
|
||||||
|
{
|
||||||
|
// When using sync interval 0, it is recommended to always pass the tearing flag when it is
|
||||||
|
// supported, even when presenting in windowed mode. However, this flag cannot be used if the app
|
||||||
|
// is in fullscreen mode as a result of calling SetFullscreenState.
|
||||||
|
UINT present_flags = 0;
|
||||||
|
if (m_allow_tearing_supported && !g_ActiveConfig.bVSyncActive && !m_has_fullscreen)
|
||||||
|
present_flags |= DXGI_PRESENT_ALLOW_TEARING;
|
||||||
|
|
||||||
|
HRESULT hr = m_swap_chain->Present(static_cast<UINT>(g_ActiveConfig.bVSyncActive), present_flags);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
WARN_LOG(VIDEO, "Swap chain present failed with HRESULT %08X", hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwapChain::ChangeSurface(void* native_handle)
|
||||||
|
{
|
||||||
|
DestroySwapChain();
|
||||||
|
m_wsi.render_surface = native_handle;
|
||||||
|
return CreateSwapChain(m_stereo);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace D3DCommon
|
74
Source/Core/VideoBackends/D3DCommon/SwapChain.h
Normal file
74
Source/Core/VideoBackends/D3DCommon/SwapChain.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2019 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <dxgi1_5.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/WindowSystemInfo.h"
|
||||||
|
#include "VideoBackends/D3DCommon/Common.h"
|
||||||
|
#include "VideoCommon/TextureConfig.h"
|
||||||
|
|
||||||
|
namespace D3DCommon
|
||||||
|
{
|
||||||
|
class SwapChain
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, IUnknown* d3d_device);
|
||||||
|
virtual ~SwapChain();
|
||||||
|
|
||||||
|
// Sufficient buffers for triple buffering.
|
||||||
|
static const u32 SWAP_CHAIN_BUFFER_COUNT = 3;
|
||||||
|
|
||||||
|
// Returns true if the stereo mode is quad-buffering.
|
||||||
|
static bool WantsStereo();
|
||||||
|
|
||||||
|
IDXGISwapChain1* GetDXGISwapChain() const { return m_swap_chain.Get(); }
|
||||||
|
AbstractTextureFormat GetFormat() const { return m_texture_format; }
|
||||||
|
u32 GetWidth() const { return m_width; }
|
||||||
|
u32 GetHeight() const { return m_height; }
|
||||||
|
u32 GetLayers() const { return m_stereo ? 2u : 1u; }
|
||||||
|
bool IsStereoEnabled() const { return m_stereo; }
|
||||||
|
bool HasExclusiveFullscreen() const { return m_has_fullscreen; }
|
||||||
|
|
||||||
|
// Mode switches.
|
||||||
|
bool GetFullscreen() const;
|
||||||
|
void SetFullscreen(bool request);
|
||||||
|
|
||||||
|
// Checks for loss of exclusive fullscreen.
|
||||||
|
bool CheckForFullscreenChange();
|
||||||
|
|
||||||
|
// Presents the swap chain to the screen.
|
||||||
|
virtual bool Present();
|
||||||
|
|
||||||
|
bool ChangeSurface(void* native_handle);
|
||||||
|
bool ResizeSwapChain();
|
||||||
|
void SetStereo(bool stereo);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u32 GetSwapChainFlags() const;
|
||||||
|
bool CreateSwapChain(bool stereo);
|
||||||
|
void DestroySwapChain();
|
||||||
|
|
||||||
|
virtual bool CreateSwapChainBuffers() = 0;
|
||||||
|
virtual void DestroySwapChainBuffers() = 0;
|
||||||
|
|
||||||
|
WindowSystemInfo m_wsi;
|
||||||
|
Microsoft::WRL::ComPtr<IDXGIFactory2> m_dxgi_factory;
|
||||||
|
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swap_chain;
|
||||||
|
Microsoft::WRL::ComPtr<IUnknown> m_d3d_device;
|
||||||
|
AbstractTextureFormat m_texture_format = AbstractTextureFormat::RGBA8;
|
||||||
|
|
||||||
|
u32 m_width = 1;
|
||||||
|
u32 m_height = 1;
|
||||||
|
|
||||||
|
bool m_stereo = false;
|
||||||
|
bool m_allow_tearing_supported = false;
|
||||||
|
bool m_has_fullscreen = false;
|
||||||
|
bool m_fullscreen_request = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace D3DCommon
|
@ -93,6 +93,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui", "..\Externals\imgui
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UpdaterCommon", "Core\UpdaterCommon\UpdaterCommon.vcxproj", "{B001D13E-7EAB-4689-842D-801E5ACFFAC5}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UpdaterCommon", "Core\UpdaterCommon\UpdaterCommon.vcxproj", "{B001D13E-7EAB-4689-842D-801E5ACFFAC5}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3DCommon", "Core\VideoBackends\D3DCommon\D3DCommon.vcxproj", "{DEA96CF2-F237-4A1A-B32F-C916769EFB50}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
@ -353,6 +355,12 @@ Global
|
|||||||
{B001D13E-7EAB-4689-842D-801E5ACFFAC5}.Release|x64.ActiveCfg = Release|x64
|
{B001D13E-7EAB-4689-842D-801E5ACFFAC5}.Release|x64.ActiveCfg = Release|x64
|
||||||
{B001D13E-7EAB-4689-842D-801E5ACFFAC5}.Release|x64.Build.0 = Release|x64
|
{B001D13E-7EAB-4689-842D-801E5ACFFAC5}.Release|x64.Build.0 = Release|x64
|
||||||
{B001D13E-7EAB-4689-842D-801E5ACFFAC5}.Release|x86.ActiveCfg = Release|x64
|
{B001D13E-7EAB-4689-842D-801E5ACFFAC5}.Release|x86.ActiveCfg = Release|x64
|
||||||
|
{DEA96CF2-F237-4A1A-B32F-C916769EFB50}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{DEA96CF2-F237-4A1A-B32F-C916769EFB50}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{DEA96CF2-F237-4A1A-B32F-C916769EFB50}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
|
{DEA96CF2-F237-4A1A-B32F-C916769EFB50}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{DEA96CF2-F237-4A1A-B32F-C916769EFB50}.Release|x64.Build.0 = Release|x64
|
||||||
|
{DEA96CF2-F237-4A1A-B32F-C916769EFB50}.Release|x86.ActiveCfg = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -394,6 +402,7 @@ Global
|
|||||||
{4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
{4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
||||||
{23114507-079A-4418-9707-CFA81A03CA99} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
{23114507-079A-4418-9707-CFA81A03CA99} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
||||||
{4C3B2264-EA73-4A7B-9CFE-65B0FD635EBB} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
{4C3B2264-EA73-4A7B-9CFE-65B0FD635EBB} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
||||||
|
{DEA96CF2-F237-4A1A-B32F-C916769EFB50} = {AAD1BCD6-9804-44A5-A5FC-4782EA00E9D4}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {710976F2-1BC7-4F2A-B32D-5DD2BBCB44E1}
|
SolutionGuid = {710976F2-1BC7-4F2A-B32D-5DD2BBCB44E1}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user