@@ -12,11 +12,12 @@
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/DXTexture.h"
#include "VideoBackends/D3DCommon/Common.h"
#include "VideoCommon/VideoConfig.h"

namespace DX11
{
DXTexture::DXTexture(const TextureConfig& config, ID3D11Texture2D* texture)
: AbstractTexture(config), m_texture(texture)
DXTexture::DXTexture(const TextureConfig& config, ComPtr<ID3D11Texture2D> texture)
: AbstractTexture(config), m_texture(std::move(texture))
{
}

@@ -41,22 +42,22 @@ std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config)
CD3D11_TEXTURE2D_DESC desc(tex_format, config.width, config.height, config.layers, config.levels,
bindflags, D3D11_USAGE_DEFAULT, 0, config.samples, 0, 0);
ComPtr<ID3D11Texture2D> d3d_texture;
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &d3d_texture);
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, d3d_texture.GetAddressOf());
if (FAILED(hr))
{
PanicAlert("Failed to create %ux%ux%u D3D backing texture", config.width, config.height,
config.layers);
return nullptr;
}

std::unique_ptr<DXTexture> tex(new DXTexture(config, d3d_texture.Get()));
std::unique_ptr<DXTexture> tex(new DXTexture(config, std::move(d3d_texture)));
if (!tex->CreateSRV() || (config.IsComputeImage() && !tex->CreateUAV()))
return nullptr;

return tex;
}

std::unique_ptr<DXTexture> DXTexture::CreateAdopted(ID3D11Texture2D* texture)
std::unique_ptr<DXTexture> DXTexture::CreateAdopted(ComPtr<ID3D11Texture2D> texture)
{
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
@@ -70,7 +71,7 @@ std::unique_ptr<DXTexture> DXTexture::CreateAdopted(ID3D11Texture2D* texture)
if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
config.flags |= AbstractTextureFlag_ComputeImage;

std::unique_ptr<DXTexture> tex(new DXTexture(config, texture));
std::unique_ptr<DXTexture> tex(new DXTexture(config, std::move(texture)));
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE && !tex->CreateSRV())
return nullptr;
if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS && !tex->CreateUAV())
@@ -87,7 +88,8 @@ bool DXTexture::CreateSRV()
D3D11_SRV_DIMENSION_TEXTURE2DARRAY,
D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, m_config.levels, 0,
m_config.layers);
HRESULT hr = D3D::device->CreateShaderResourceView(m_texture.Get(), &desc, &m_srv);
DEBUG_ASSERT(!m_srv);
HRESULT hr = D3D::device->CreateShaderResourceView(m_texture.Get(), &desc, m_srv.GetAddressOf());
if (FAILED(hr))
{
PanicAlert("Failed to create %ux%ux%u D3D SRV", m_config.width, m_config.height,
@@ -103,7 +105,8 @@ bool DXTexture::CreateUAV()
const CD3D11_UNORDERED_ACCESS_VIEW_DESC desc(
m_texture.Get(), D3D11_UAV_DIMENSION_TEXTURE2DARRAY,
D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, 0, m_config.layers);
HRESULT hr = D3D::device->CreateUnorderedAccessView(m_texture.Get(), &desc, &m_uav);
DEBUG_ASSERT(!m_uav);
HRESULT hr = D3D::device->CreateUnorderedAccessView(m_texture.Get(), &desc, m_uav.GetAddressOf());
if (FAILED(hr))
{
PanicAlert("Failed to create %ux%ux%u D3D UAV", m_config.width, m_config.height,
@@ -161,8 +164,8 @@ void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8*
}

DXStagingTexture::DXStagingTexture(StagingTextureType type, const TextureConfig& config,
ID3D11Texture2D* tex)
: AbstractStagingTexture(type, config), m_tex(tex)
ComPtr<ID3D11Texture2D> tex)
: AbstractStagingTexture(type, config), m_tex(std::move(tex))
{
}

@@ -197,12 +200,12 @@ std::unique_ptr<DXStagingTexture> DXStagingTexture::Create(StagingTextureType ty
config.width, config.height, 1, 1, 0, usage, cpu_flags);

ComPtr<ID3D11Texture2D> texture;
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &texture);
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, texture.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create staging texture");
if (FAILED(hr))
return nullptr;

return std::unique_ptr<DXStagingTexture>(new DXStagingTexture(type, config, texture.Get()));
return std::unique_ptr<DXStagingTexture>(new DXStagingTexture(type, config, std::move(texture)));
}

void DXStagingTexture::CopyFromTexture(const AbstractTexture* src,
@@ -316,11 +319,12 @@ void DXStagingTexture::Flush()
DXFramebuffer::DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
u32 width, u32 height, u32 layers, u32 samples,
ID3D11RenderTargetView* rtv, ID3D11RenderTargetView* integer_rtv,
ID3D11DepthStencilView* dsv)
ComPtr<ID3D11RenderTargetView> rtv,
ComPtr<ID3D11RenderTargetView> integer_rtv,
ComPtr<ID3D11DepthStencilView> dsv)
: AbstractFramebuffer(color_attachment, depth_attachment, color_format, depth_format, width,
height, layers, samples),
m_rtv(rtv), m_integer_rtv(integer_rtv), m_dsv(dsv)
m_rtv(std::move(rtv)), m_integer_rtv(std::move(integer_rtv)), m_dsv(std::move(dsv))
{
}

@@ -351,20 +355,20 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
D3D11_RTV_DIMENSION_TEXTURE2DARRAY,
D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), false), 0, 0,
color_attachment->GetLayers());
HRESULT hr =
D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc, &rtv);
HRESULT hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,
rtv.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create render target view for framebuffer");
if (FAILED(hr))
return nullptr;

// Only create the integer RTV on Win8+.
// Only create the integer RTV when logic ops are supported (Win8+).
DXGI_FORMAT integer_format =
D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), true);
if (D3D::device1 && integer_format != desc.Format)
if (g_ActiveConfig.backend_info.bSupportsLogicOp && integer_format != desc.Format)
{
desc.Format = integer_format;
hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,
&integer_rtv);
integer_rtv.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create integer render target view for framebuffer");
}
}
@@ -377,16 +381,16 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
D3D11_DSV_DIMENSION_TEXTURE2DARRAY,
D3DCommon::GetDSVFormatForAbstractFormat(depth_attachment->GetFormat()), 0, 0,
depth_attachment->GetLayers(), 0);
HRESULT hr =
D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc, &dsv);
HRESULT hr = D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc,
dsv.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer");
if (FAILED(hr))
return nullptr;
}

return std::make_unique<DXFramebuffer>(color_attachment, depth_attachment, color_format,
depth_format, width, height, layers, samples, rtv.Get(),
integer_rtv.Get(), dsv.Get());
depth_format, width, height, layers, samples,
std::move(rtv), std::move(integer_rtv), std::move(dsv));
}

} // namespace DX11
@@ -20,7 +20,7 @@ class DXTexture final : public AbstractTexture
~DXTexture();

static std::unique_ptr<DXTexture> Create(const TextureConfig& config);
static std::unique_ptr<DXTexture> CreateAdopted(ID3D11Texture2D* texture);
static std::unique_ptr<DXTexture> CreateAdopted(ComPtr<ID3D11Texture2D> texture);

void CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
@@ -36,7 +36,7 @@ class DXTexture final : public AbstractTexture
ID3D11UnorderedAccessView* GetD3DUAV() const { return m_uav.Get(); }

private:
DXTexture(const TextureConfig& config, ID3D11Texture2D* texture);
DXTexture(const TextureConfig& config, ComPtr<ID3D11Texture2D> texture);

bool CreateSRV();
bool CreateUAV();
@@ -67,7 +67,8 @@ class DXStagingTexture final : public AbstractStagingTexture
const TextureConfig& config);

private:
DXStagingTexture(StagingTextureType type, const TextureConfig& config, ID3D11Texture2D* tex);
DXStagingTexture(StagingTextureType type, const TextureConfig& config,
ComPtr<ID3D11Texture2D> tex);

ComPtr<ID3D11Texture2D> m_tex = nullptr;
};
@@ -77,8 +78,8 @@ class DXFramebuffer final : public AbstractFramebuffer
public:
DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
u32 height, u32 layers, u32 samples, ID3D11RenderTargetView* rtv,
ID3D11RenderTargetView* integer_rtv, ID3D11DepthStencilView* dsv);
u32 height, u32 layers, u32 samples, ComPtr<ID3D11RenderTargetView> rtv,
ComPtr<ID3D11RenderTargetView> integer_rtv, ComPtr<ID3D11DepthStencilView> dsv);
~DXFramebuffer() override;

ID3D11RenderTargetView* const* GetRTVArray() const { return m_rtv.GetAddressOf(); }
@@ -82,10 +82,10 @@ void Renderer::Create3DVisionTexture(int width, int height)

CD3D11_TEXTURE2D_DESC texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, width * 2, height + 1, 1, 1,
D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0, 0);
ID3D11Texture2D* texture;
HRESULT hr = D3D::device->CreateTexture2D(&texture_desc, &sys_data, &texture);
ComPtr<ID3D11Texture2D> texture;
HRESULT hr = D3D::device->CreateTexture2D(&texture_desc, &sys_data, texture.GetAddressOf());
CHECK(SUCCEEDED(hr), "Create 3D Vision Texture");
m_3d_vision_texture = DXTexture::CreateAdopted(texture);
m_3d_vision_texture = DXTexture::CreateAdopted(std::move(texture));
m_3d_vision_framebuffer = DXFramebuffer::Create(m_3d_vision_texture.get(), nullptr);
}

@@ -33,7 +33,7 @@ bool SwapChain::CreateSwapChainBuffers()
if (FAILED(hr))
return false;

m_texture = DXTexture::CreateAdopted(texture.Get());
m_texture = DXTexture::CreateAdopted(std::move(texture));
if (!m_texture)
return false;

@@ -17,6 +17,7 @@ class VideoBackend : public VideoBackendBase

std::string GetName() const override;
std::string GetDisplayName() const override;
std::optional<std::string> GetWarningMessage() const override;

void InitBackendInfo() override;

@@ -37,6 +37,31 @@ std::string VideoBackend::GetDisplayName() const
return _trans("Direct3D 11");
}

std::optional<std::string> VideoBackend::GetWarningMessage() const
{
std::optional<std::string> result;

// If user is on Win7, show a warning about partial DX11.1 support
// This is being called BEFORE FillBackendInfo is called for this backend,
// so query for logic op support manually
bool supportsLogicOp = false;
if (D3DCommon::LoadLibraries())
{
supportsLogicOp = D3D::SupportsLogicOp(g_Config.iAdapter);
D3DCommon::UnloadLibraries();
}

if (!supportsLogicOp)
{
result = _trans("Direct3D 11 renderer requires support for features not supported by your "
"system configuration. This is most likely because you are using Windows 7. "
"You may still use this backend, but you might encounter graphical artifacts."
"\n\nDo you really want to switch to Direct3D 11? If unsure, select 'No'.");
}

return result;
}

void VideoBackend::InitBackendInfo()
{
if (!D3DCommon::LoadLibraries())
@@ -63,16 +88,13 @@ void VideoBackend::FillBackendInfo()
g_Config.backend_info.bSupportsClipControl = true;
g_Config.backend_info.bSupportsDepthClamp = true;
g_Config.backend_info.bSupportsReversedDepthRange = false;
g_Config.backend_info.bSupportsLogicOp = true;
g_Config.backend_info.bSupportsMultithreading = false;
g_Config.backend_info.bSupportsGPUTextureDecoding = true;
g_Config.backend_info.bSupportsST3CTextures = false;
g_Config.backend_info.bSupportsCopyToVram = true;
g_Config.backend_info.bSupportsLargePoints = false;
g_Config.backend_info.bSupportsPartialDepthCopies = false;
g_Config.backend_info.bSupportsBitfield = false;
g_Config.backend_info.bSupportsDynamicSamplerIndexing = false;
g_Config.backend_info.bSupportsBPTCTextures = false;
g_Config.backend_info.bSupportsFramebufferFetch = false;
g_Config.backend_info.bSupportsBackgroundCompiling = true;
g_Config.backend_info.bSupportsST3CTextures = true;
@@ -84,6 +106,7 @@ void VideoBackend::FillBackendInfo()
g_Config.backend_info.bSupportsSSAA = true;
g_Config.backend_info.bSupportsShaderBinaries = true;
g_Config.backend_info.bSupportsPipelineCacheData = false;
g_Config.backend_info.bSupportsLogicOp = D3D::SupportsLogicOp(g_Config.iAdapter);

g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames();
g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter);
@@ -180,7 +180,7 @@ bool DXContext::CreateDevice(u32 adapter_index, bool enable_debug_layer)
if (enable_debug_layer)
{
ComPtr<ID3D12InfoQueue> info_queue;
if (SUCCEEDED(m_device->QueryInterface(IID_PPV_ARGS(&info_queue))))
if (SUCCEEDED(m_device.As(&info_queue)))
{
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);
@@ -53,6 +53,13 @@ std::string VideoSoftware::GetDisplayName() const
return _trans("Software Renderer");
}

std::optional<std::string> VideoSoftware::GetWarningMessage() const
{
return _trans("The software renderer is significantly slower than other "
"backends and is only recommended for debugging purposes.\n\nDo you "
"really want to enable software rendering? If unsure, select 'No'.");
}

void VideoSoftware::InitBackendInfo()
{
g_Config.backend_info.api_type = APIType::Nothing;
@@ -16,6 +16,7 @@ class VideoSoftware : public VideoBackendBase

std::string GetName() const override;
std::string GetDisplayName() const override;
std::optional<std::string> GetWarningMessage() const override;

void InitBackendInfo() override;
};
@@ -5,6 +5,7 @@
#pragma once

#include <memory>
#include <optional>
#include <string>
#include <vector>

@@ -42,6 +43,7 @@ class VideoBackendBase
virtual std::string GetName() const = 0;
virtual std::string GetDisplayName() const { return GetName(); }
virtual void InitBackendInfo() = 0;
virtual std::optional<std::string> GetWarningMessage() const { return {}; }

// Prepares a native window for rendering. This is called on the main thread, or the
// thread which owns the window.