1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-15 07:29:17 +01:00

[vulkan,d3d9,d3d11] Move surface creation to swap chain implementation

This commit is contained in:
Philip Rebohle 2022-10-28 15:52:43 +02:00
parent 49cf0ecf54
commit 03dca539cb
8 changed files with 129 additions and 68 deletions

View File

@ -2,6 +2,7 @@
#include <cstring> #include <cstring>
#include "../dxgi/dxgi_monitor.h" #include "../dxgi/dxgi_monitor.h"
#include "../dxgi/dxgi_surface.h"
#include "../dxgi/dxgi_swapchain.h" #include "../dxgi/dxgi_swapchain.h"
#include "../dxvk/dxvk_adapter.h" #include "../dxvk/dxvk_adapter.h"
@ -3002,8 +3003,12 @@ namespace dxvk {
InitReturnPtr(ppSwapChain); InitReturnPtr(ppSwapChain);
try { try {
auto vki = m_device->GetDXVKDevice()->adapter()->vki();
Com<IDXGIVkSurfaceFactory> surfaceFactory = new DxgiSurfaceFactory(vki->getLoaderProc(), hWnd);
Com<D3D11SwapChain> presenter = new D3D11SwapChain( Com<D3D11SwapChain> presenter = new D3D11SwapChain(
m_container, m_device, hWnd, pDesc); m_container, m_device, surfaceFactory.ptr(), pDesc);
*ppSwapChain = presenter.ref(); *ppSwapChain = presenter.ref();
return S_OK; return S_OK;
@ -3074,9 +3079,14 @@ namespace dxvk {
} }
try { try {
auto vki = m_device->GetDXVKDevice()->adapter()->vki();
// Create surface factory for the window
Com<IDXGIVkSurfaceFactory> surfaceFactory = new DxgiSurfaceFactory(vki->getLoaderProc(), hWnd);
// Create presenter for the device // Create presenter for the device
Com<D3D11SwapChain> presenter = new D3D11SwapChain( Com<D3D11SwapChain> presenter = new D3D11SwapChain(
m_container, m_device, hWnd, &desc); m_container, m_device, surfaceFactory.ptr(), &desc);
// Create the actual swap chain // Create the actual swap chain
*ppSwapChain = ref(new DxgiSwapChain( *ppSwapChain = ref(new DxgiSwapChain(

View File

@ -16,23 +16,23 @@ namespace dxvk {
D3D11SwapChain::D3D11SwapChain( D3D11SwapChain::D3D11SwapChain(
D3D11DXGIDevice* pContainer, D3D11DXGIDevice* pContainer,
D3D11Device* pDevice, D3D11Device* pDevice,
HWND hWnd, IDXGIVkSurfaceFactory* pSurfaceFactory,
const DXGI_SWAP_CHAIN_DESC1* pDesc) const DXGI_SWAP_CHAIN_DESC1* pDesc)
: m_dxgiDevice(pContainer), : m_dxgiDevice(pContainer),
m_parent(pDevice), m_parent(pDevice),
m_window (hWnd), m_surfaceFactory(pSurfaceFactory),
m_desc(*pDesc), m_desc(*pDesc),
m_device(pDevice->GetDXVKDevice()), m_device(pDevice->GetDXVKDevice()),
m_context(m_device->createContext(DxvkContextType::Supplementary)), m_context(m_device->createContext(DxvkContextType::Supplementary)),
m_frameLatencyCap(pDevice->GetOptions()->maxFrameLatency) { m_frameLatencyCap(pDevice->GetOptions()->maxFrameLatency) {
CreateFrameLatencyEvent(); CreateFrameLatencyEvent();
if (!pDevice->GetOptions()->deferSurfaceCreation)
CreatePresenter(); CreatePresenter();
CreateBackBuffer(); CreateBackBuffer();
CreateBlitter(); CreateBlitter();
CreateHud(); CreateHud();
if (!pDevice->GetOptions()->deferSurfaceCreation)
RecreateSwapChain(false);
} }
@ -223,9 +223,6 @@ namespace dxvk {
m_vsync = vsync; m_vsync = vsync;
} }
if (m_presenter == nullptr)
CreatePresenter();
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!m_presenter->hasSwapChain()) { if (!m_presenter->hasSwapChain()) {
@ -395,8 +392,21 @@ namespace dxvk {
presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes); presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes);
presenterDesc.fullScreenExclusive = PickFullscreenMode(); presenterDesc.fullScreenExclusive = PickFullscreenMode();
if (m_presenter->recreateSwapChain(presenterDesc) != VK_SUCCESS) VkResult vr = m_presenter->recreateSwapChain(presenterDesc);
throw DxvkError("D3D11SwapChain: Failed to recreate swap chain");
if (vr == VK_ERROR_SURFACE_LOST_KHR) {
vr = m_presenter->recreateSurface([this] (VkSurfaceKHR* surface) {
return CreateSurface(surface);
});
if (vr)
throw DxvkError(str::format("D3D11SwapChain: Failed to recreate surface: ", vr));
vr = m_presenter->recreateSwapChain(presenterDesc);
}
if (vr)
throw DxvkError(str::format("D3D11SwapChain: Failed to recreate swap chain: ", vr));
CreateRenderTargetViews(); CreateRenderTargetViews();
} }
@ -426,15 +436,22 @@ namespace dxvk {
presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes); presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes);
presenterDesc.fullScreenExclusive = PickFullscreenMode(); presenterDesc.fullScreenExclusive = PickFullscreenMode();
m_presenter = new vk::Presenter(m_window, m_presenter = new vk::Presenter(
m_device->adapter()->vki(), m_device->adapter()->vki(),
m_device->vkd(), m_device->vkd(),
presenterDevice, presenterDevice,
presenterDesc); presenterDesc);
m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate); m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
}
CreateRenderTargetViews();
VkResult D3D11SwapChain::CreateSurface(VkSurfaceKHR* pSurface) {
Rc<DxvkAdapter> adapter = m_device->adapter();
return m_surfaceFactory->CreateSurface(
adapter->vki()->instance(),
adapter->handle(), pSurface);
} }

View File

@ -20,7 +20,7 @@ namespace dxvk {
D3D11SwapChain( D3D11SwapChain(
D3D11DXGIDevice* pContainer, D3D11DXGIDevice* pContainer,
D3D11Device* pDevice, D3D11Device* pDevice,
HWND hWnd, IDXGIVkSurfaceFactory* pSurfaceFactory,
const DXGI_SWAP_CHAIN_DESC1* pDesc); const DXGI_SWAP_CHAIN_DESC1* pDesc);
~D3D11SwapChain(); ~D3D11SwapChain();
@ -90,7 +90,7 @@ namespace dxvk {
Com<D3D11DXGIDevice, false> m_dxgiDevice; Com<D3D11DXGIDevice, false> m_dxgiDevice;
D3D11Device* m_parent; D3D11Device* m_parent;
HWND m_window; Com<IDXGIVkSurfaceFactory> m_surfaceFactory;
DXGI_SWAP_CHAIN_DESC1 m_desc; DXGI_SWAP_CHAIN_DESC1 m_desc;
@ -137,6 +137,8 @@ namespace dxvk {
void CreatePresenter(); void CreatePresenter();
VkResult CreateSurface(VkSurfaceKHR* pSurface);
void CreateRenderTargetViews(); void CreateRenderTargetViews();
void CreateBackBuffer(); void CreateBackBuffer();

View File

@ -35,9 +35,14 @@ namespace dxvk {
m_window = m_presentParams.hDeviceWindow; m_window = m_presentParams.hDeviceWindow;
UpdatePresentRegion(nullptr, nullptr); UpdatePresentRegion(nullptr, nullptr);
if (m_window && !pDevice->GetOptions()->deferSurfaceCreation)
if (m_window) {
CreatePresenter(); CreatePresenter();
if (!pDevice->GetOptions()->deferSurfaceCreation)
RecreateSwapChain(false);
}
CreateBackBuffers(m_presentParams.BackBufferCount); CreateBackBuffers(m_presentParams.BackBufferCount);
CreateBlitter(); CreateBlitter();
CreateHud(); CreateHud();
@ -757,8 +762,21 @@ namespace dxvk {
presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes); presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes);
presenterDesc.fullScreenExclusive = PickFullscreenMode(); presenterDesc.fullScreenExclusive = PickFullscreenMode();
if (m_presenter->recreateSwapChain(presenterDesc) != VK_SUCCESS) VkResult vr = m_presenter->recreateSwapChain(presenterDesc);
throw DxvkError("D3D9SwapChainEx: Failed to recreate swap chain");
if (vr == VK_ERROR_SURFACE_LOST_KHR) {
vr = m_presenter->recreateSurface([this] (VkSurfaceKHR* surface) {
return CreateSurface(surface);
});
if (vr)
throw DxvkError(str::format("D3D9SwapChainEx: Failed to recreate surface: ", vr));
vr = m_presenter->recreateSwapChain(presenterDesc);
}
if (vr)
throw DxvkError(str::format("D3D9SwapChainEx: Failed to recreate swap chain: ", vr));
CreateRenderTargetViews(); CreateRenderTargetViews();
} }
@ -785,15 +803,23 @@ namespace dxvk {
presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes); presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes);
presenterDesc.fullScreenExclusive = PickFullscreenMode(); presenterDesc.fullScreenExclusive = PickFullscreenMode();
m_presenter = new vk::Presenter(m_window, m_presenter = new vk::Presenter(
m_device->adapter()->vki(), m_device->adapter()->vki(),
m_device->vkd(), m_device->vkd(),
presenterDevice, presenterDevice,
presenterDesc); presenterDesc);
m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate); m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
}
CreateRenderTargetViews();
VkResult D3D9SwapChainEx::CreateSurface(VkSurfaceKHR* pSurface) {
auto vki = m_device->adapter()->vki();
return wsi::createSurface(m_window,
vki->getLoaderProc(),
vki->instance(),
pSurface);
} }

View File

@ -137,6 +137,8 @@ namespace dxvk {
void CreatePresenter(); void CreatePresenter();
VkResult CreateSurface(VkSurfaceKHR* pSurface);
void CreateRenderTargetViews(); void CreateRenderTargetViews();
void DestroyBackBuffers(); void DestroyBackBuffers();

View File

@ -23,6 +23,7 @@ namespace dxvk::vk {
~LibraryLoader(); ~LibraryLoader();
PFN_vkVoidFunction sym(VkInstance instance, const char* name) const; PFN_vkVoidFunction sym(VkInstance instance, const char* name) const;
PFN_vkVoidFunction sym(const char* name) const; PFN_vkVoidFunction sym(const char* name) const;
PFN_vkGetInstanceProcAddr getLoaderProc() const { return m_getInstanceProcAddr; }
bool valid() const; bool valid() const;
protected: protected:
const HMODULE m_library; const HMODULE m_library;
@ -39,6 +40,7 @@ namespace dxvk::vk {
struct InstanceLoader : public RcObject { struct InstanceLoader : public RcObject {
InstanceLoader(const Rc<LibraryLoader>& library, bool owned, VkInstance instance); InstanceLoader(const Rc<LibraryLoader>& library, bool owned, VkInstance instance);
PFN_vkVoidFunction sym(const char* name) const; PFN_vkVoidFunction sym(const char* name) const;
PFN_vkGetInstanceProcAddr getLoaderProc() const { return m_library->getLoaderProc(); }
VkInstance instance() const { return m_instance; } VkInstance instance() const { return m_instance; }
protected: protected:
Rc<LibraryLoader> m_library; Rc<LibraryLoader> m_library;

View File

@ -7,17 +7,12 @@
namespace dxvk::vk { namespace dxvk::vk {
Presenter::Presenter( Presenter::Presenter(
HWND window,
const Rc<InstanceFn>& vki, const Rc<InstanceFn>& vki,
const Rc<DeviceFn>& vkd, const Rc<DeviceFn>& vkd,
PresenterDevice device, PresenterDevice device,
const PresenterDesc& desc) const PresenterDesc& desc)
: m_vki(vki), m_vkd(vkd), m_device(device), m_window(window) { : m_vki(vki), m_vkd(vkd), m_device(device) {
if (createSurface() != VK_SUCCESS)
throw DxvkError("Failed to create surface");
if (recreateSwapChain(desc) != VK_SUCCESS)
throw DxvkError("Failed to create swap chain");
} }
@ -89,10 +84,25 @@ namespace dxvk::vk {
} }
VkResult Presenter::recreateSurface(
const std::function<VkResult (VkSurfaceKHR*)>& fn) {
if (m_swapchain)
destroySwapchain();
if (m_surface)
destroySurface();
return fn(&m_surface);
}
VkResult Presenter::recreateSwapChain(const PresenterDesc& desc) { VkResult Presenter::recreateSwapChain(const PresenterDesc& desc) {
if (m_swapchain) if (m_swapchain)
destroySwapchain(); destroySwapchain();
if (!m_surface)
return VK_ERROR_SURFACE_LOST_KHR;
// Query surface capabilities. Some properties might // Query surface capabilities. Some properties might
// have changed, including the size limits and supported // have changed, including the size limits and supported
// present modes, so we'll just query everything again. // present modes, so we'll just query everything again.
@ -103,13 +113,13 @@ namespace dxvk::vk {
VkResult status; VkResult status;
if ((status = m_vki->vkGetPhysicalDeviceSurfaceCapabilitiesKHR( if ((status = m_vki->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
m_device.adapter, m_surface, &caps)) != VK_SUCCESS) m_device.adapter, m_surface, &caps)))
return status; return status;
if ((status = getSupportedFormats(formats, desc)) != VK_SUCCESS) if ((status = getSupportedFormats(formats, desc)))
return status; return status;
if ((status = getSupportedPresentModes(modes, desc)) != VK_SUCCESS) if ((status = getSupportedPresentModes(modes, desc)))
return status; return status;
// Select actual swap chain properties and create swap chain // Select actual swap chain properties and create swap chain
@ -155,13 +165,13 @@ namespace dxvk::vk {
"\n Exclusive FS: ", desc.fullScreenExclusive)); "\n Exclusive FS: ", desc.fullScreenExclusive));
if ((status = m_vkd->vkCreateSwapchainKHR(m_vkd->device(), if ((status = m_vkd->vkCreateSwapchainKHR(m_vkd->device(),
&swapInfo, nullptr, &m_swapchain)) != VK_SUCCESS) &swapInfo, nullptr, &m_swapchain)))
return status; return status;
// Acquire images and create views // Acquire images and create views
std::vector<VkImage> images; std::vector<VkImage> images;
if ((status = getSwapImages(images)) != VK_SUCCESS) if ((status = getSwapImages(images)))
return status; return status;
// Update actual image count // Update actual image count
@ -183,7 +193,7 @@ namespace dxvk::vk {
0, 1, 0, 1 }; 0, 1, 0, 1 };
if ((status = m_vkd->vkCreateImageView(m_vkd->device(), if ((status = m_vkd->vkCreateImageView(m_vkd->device(),
&viewInfo, nullptr, &m_images[i].view)) != VK_SUCCESS) &viewInfo, nullptr, &m_images[i].view)))
return status; return status;
} }
@ -194,11 +204,11 @@ namespace dxvk::vk {
VkSemaphoreCreateInfo semInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; VkSemaphoreCreateInfo semInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
if ((status = m_vkd->vkCreateSemaphore(m_vkd->device(), if ((status = m_vkd->vkCreateSemaphore(m_vkd->device(),
&semInfo, nullptr, &m_semaphores[i].acquire)) != VK_SUCCESS) &semInfo, nullptr, &m_semaphores[i].acquire)))
return status; return status;
if ((status = m_vkd->vkCreateSemaphore(m_vkd->device(), if ((status = m_vkd->vkCreateSemaphore(m_vkd->device(),
&semInfo, nullptr, &m_semaphores[i].present)) != VK_SUCCESS) &semInfo, nullptr, &m_semaphores[i].present)))
return status; return status;
} }
@ -398,28 +408,6 @@ namespace dxvk::vk {
} }
VkResult Presenter::createSurface() {
/* TODO fix */
VkResult status = wsi::createSurface(m_window, nullptr, m_vki->instance(), &m_surface);
if (status != VK_SUCCESS)
return status;
VkBool32 supportStatus = VK_FALSE;
if ((status = m_vki->vkGetPhysicalDeviceSurfaceSupportKHR(m_device.adapter,
m_device.queueFamily, m_surface, &supportStatus)) != VK_SUCCESS)
return status;
if (!supportStatus) {
m_vki->vkDestroySurfaceKHR(m_vki->instance(), m_surface, nullptr);
return VK_ERROR_OUT_OF_HOST_MEMORY; // just abuse this
}
return VK_SUCCESS;
}
void Presenter::destroySwapchain() { void Presenter::destroySwapchain() {
for (const auto& img : m_images) for (const auto& img : m_images)
m_vkd->vkDestroyImageView(m_vkd->device(), img.view, nullptr); m_vkd->vkDestroyImageView(m_vkd->device(), img.view, nullptr);
@ -440,6 +428,8 @@ namespace dxvk::vk {
void Presenter::destroySurface() { void Presenter::destroySurface() {
m_vki->vkDestroySurfaceKHR(m_vki->instance(), m_surface, nullptr); m_vki->vkDestroySurfaceKHR(m_vki->instance(), m_surface, nullptr);
m_surface = VK_NULL_HANDLE;
} }
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <functional>
#include <vector> #include <vector>
#include "../util/log/log.h" #include "../util/log/log.h"
@ -93,7 +94,6 @@ namespace dxvk::vk {
public: public:
Presenter( Presenter(
HWND window,
const Rc<InstanceFn>& vki, const Rc<InstanceFn>& vki,
const Rc<DeviceFn>& vkd, const Rc<DeviceFn>& vkd,
PresenterDevice device, PresenterDevice device,
@ -142,6 +142,15 @@ namespace dxvk::vk {
*/ */
VkResult presentImage(); VkResult presentImage();
/**
* \brief Changes and takes ownership of surface
*
* The presenter will destroy the surface as necessary.
* \param [in] fn Surface create function
*/
VkResult recreateSurface(
const std::function<VkResult (VkSurfaceKHR*)>& fn);
/** /**
* \brief Changes presenter properties * \brief Changes presenter properties
* *
@ -149,6 +158,7 @@ namespace dxvk::vk {
* no swap chain resources must be in use by the * no swap chain resources must be in use by the
* GPU at the time this is called. * GPU at the time this is called.
* \param [in] desc Swap chain description * \param [in] desc Swap chain description
* \param [in] surface New Vulkan surface
*/ */
VkResult recreateSwapChain( VkResult recreateSwapChain(
const PresenterDesc& desc); const PresenterDesc& desc);
@ -181,7 +191,6 @@ namespace dxvk::vk {
PresenterDevice m_device; PresenterDevice m_device;
PresenterInfo m_info; PresenterInfo m_info;
HWND m_window = nullptr;
VkSurfaceKHR m_surface = VK_NULL_HANDLE; VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE; VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
@ -195,6 +204,9 @@ namespace dxvk::vk {
FpsLimiter m_fpsLimiter; FpsLimiter m_fpsLimiter;
VkResult recreateSwapChainInternal(
const PresenterDesc& desc);
VkResult getSupportedFormats( VkResult getSupportedFormats(
std::vector<VkSurfaceFormatKHR>& formats, std::vector<VkSurfaceFormatKHR>& formats,
const PresenterDesc& desc); const PresenterDesc& desc);