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

View File

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

View File

@ -35,9 +35,14 @@ namespace dxvk {
m_window = m_presentParams.hDeviceWindow;
UpdatePresentRegion(nullptr, nullptr);
if (m_window && !pDevice->GetOptions()->deferSurfaceCreation)
if (m_window) {
CreatePresenter();
if (!pDevice->GetOptions()->deferSurfaceCreation)
RecreateSwapChain(false);
}
CreateBackBuffers(m_presentParams.BackBufferCount);
CreateBlitter();
CreateHud();
@ -116,7 +121,7 @@ namespace dxvk {
bool recreate = false;
recreate |= m_presenter == nullptr;
recreate |= window != m_window;
recreate |= window != m_window;
recreate |= m_dialog != m_lastDialog;
m_window = window;
@ -757,8 +762,21 @@ namespace dxvk {
presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes);
presenterDesc.fullScreenExclusive = PickFullscreenMode();
if (m_presenter->recreateSwapChain(presenterDesc) != VK_SUCCESS)
throw DxvkError("D3D9SwapChainEx: Failed to recreate swap chain");
VkResult vr = m_presenter->recreateSwapChain(presenterDesc);
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();
}
@ -785,15 +803,23 @@ namespace dxvk {
presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes);
presenterDesc.fullScreenExclusive = PickFullscreenMode();
m_presenter = new vk::Presenter(m_window,
m_presenter = new vk::Presenter(
m_device->adapter()->vki(),
m_device->vkd(),
presenterDevice,
presenterDesc);
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();
VkResult CreateSurface(VkSurfaceKHR* pSurface);
void CreateRenderTargetViews();
void DestroyBackBuffers();

View File

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

View File

@ -7,17 +7,12 @@
namespace dxvk::vk {
Presenter::Presenter(
HWND window,
const Rc<InstanceFn>& vki,
const Rc<DeviceFn>& vkd,
PresenterDevice device,
const PresenterDesc& desc)
: m_vki(vki), m_vkd(vkd), m_device(device), m_window(window) {
if (createSurface() != VK_SUCCESS)
throw DxvkError("Failed to create surface");
: m_vki(vki), m_vkd(vkd), m_device(device) {
if (recreateSwapChain(desc) != VK_SUCCESS)
throw DxvkError("Failed to create swap chain");
}
@ -46,7 +41,7 @@ namespace dxvk::vk {
m_swapchain, std::numeric_limits<uint64_t>::max(),
sync.acquire, VK_NULL_HANDLE, &m_imageIndex);
}
if (m_acquireStatus != VK_SUCCESS && m_acquireStatus != VK_SUBOPTIMAL_KHR)
return m_acquireStatus;
@ -88,11 +83,26 @@ namespace dxvk::vk {
return status;
}
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) {
if (m_swapchain)
destroySwapchain();
if (!m_surface)
return VK_ERROR_SURFACE_LOST_KHR;
// Query surface capabilities. Some properties might
// have changed, including the size limits and supported
// present modes, so we'll just query everything again.
@ -103,13 +113,13 @@ namespace dxvk::vk {
VkResult status;
if ((status = m_vki->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
m_device.adapter, m_surface, &caps)) != VK_SUCCESS)
m_device.adapter, m_surface, &caps)))
return status;
if ((status = getSupportedFormats(formats, desc)) != VK_SUCCESS)
if ((status = getSupportedFormats(formats, desc)))
return status;
if ((status = getSupportedPresentModes(modes, desc)) != VK_SUCCESS)
if ((status = getSupportedPresentModes(modes, desc)))
return status;
// Select actual swap chain properties and create swap chain
@ -155,13 +165,13 @@ namespace dxvk::vk {
"\n Exclusive FS: ", desc.fullScreenExclusive));
if ((status = m_vkd->vkCreateSwapchainKHR(m_vkd->device(),
&swapInfo, nullptr, &m_swapchain)) != VK_SUCCESS)
&swapInfo, nullptr, &m_swapchain)))
return status;
// Acquire images and create views
std::vector<VkImage> images;
if ((status = getSwapImages(images)) != VK_SUCCESS)
if ((status = getSwapImages(images)))
return status;
// Update actual image count
@ -183,7 +193,7 @@ namespace dxvk::vk {
0, 1, 0, 1 };
if ((status = m_vkd->vkCreateImageView(m_vkd->device(),
&viewInfo, nullptr, &m_images[i].view)) != VK_SUCCESS)
&viewInfo, nullptr, &m_images[i].view)))
return status;
}
@ -194,11 +204,11 @@ namespace dxvk::vk {
VkSemaphoreCreateInfo semInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
if ((status = m_vkd->vkCreateSemaphore(m_vkd->device(),
&semInfo, nullptr, &m_semaphores[i].acquire)) != VK_SUCCESS)
&semInfo, nullptr, &m_semaphores[i].acquire)))
return status;
if ((status = m_vkd->vkCreateSemaphore(m_vkd->device(),
&semInfo, nullptr, &m_semaphores[i].present)) != VK_SUCCESS)
&semInfo, nullptr, &m_semaphores[i].present)))
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() {
for (const auto& img : m_images)
m_vkd->vkDestroyImageView(m_vkd->device(), img.view, nullptr);
@ -440,6 +428,8 @@ namespace dxvk::vk {
void Presenter::destroySurface() {
m_vki->vkDestroySurfaceKHR(m_vki->instance(), m_surface, nullptr);
m_surface = VK_NULL_HANDLE;
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <functional>
#include <vector>
#include "../util/log/log.h"
@ -93,7 +94,6 @@ namespace dxvk::vk {
public:
Presenter(
HWND window,
const Rc<InstanceFn>& vki,
const Rc<DeviceFn>& vkd,
PresenterDevice device,
@ -141,7 +141,16 @@ namespace dxvk::vk {
* \returns Status of the operation
*/
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
*
@ -149,6 +158,7 @@ namespace dxvk::vk {
* no swap chain resources must be in use by the
* GPU at the time this is called.
* \param [in] desc Swap chain description
* \param [in] surface New Vulkan surface
*/
VkResult recreateSwapChain(
const PresenterDesc& desc);
@ -181,7 +191,6 @@ namespace dxvk::vk {
PresenterDevice m_device;
PresenterInfo m_info;
HWND m_window = nullptr;
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
@ -195,6 +204,9 @@ namespace dxvk::vk {
FpsLimiter m_fpsLimiter;
VkResult recreateSwapChainInternal(
const PresenterDesc& desc);
VkResult getSupportedFormats(
std::vector<VkSurfaceFormatKHR>& formats,
const PresenterDesc& desc);