mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-13 19:29:14 +01:00
[vulkan,d3d9,d3d11] Move surface creation to swap chain implementation
This commit is contained in:
parent
49cf0ecf54
commit
03dca539cb
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -137,6 +137,8 @@ namespace dxvk {
|
||||
|
||||
void CreatePresenter();
|
||||
|
||||
VkResult CreateSurface(VkSurfaceKHR* pSurface);
|
||||
|
||||
void CreateRenderTargetViews();
|
||||
|
||||
void DestroyBackBuffers();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user