mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-02 13:29:14 +01:00
[dxgi] Refactor Vulkan swap chain and surface creation
Creating the Vulkan surface at the latest possible moment fixes an issue with Frostpunk, which renders to a D3D9 swap chain before presenting to the GXGI swap chain.
This commit is contained in:
parent
531732fe91
commit
38c5e57025
@ -10,15 +10,10 @@ namespace dxvk {
|
|||||||
DxgiVkPresenter::DxgiVkPresenter(
|
DxgiVkPresenter::DxgiVkPresenter(
|
||||||
const Rc<DxvkDevice>& device,
|
const Rc<DxvkDevice>& device,
|
||||||
HWND window)
|
HWND window)
|
||||||
: m_device (device),
|
: m_window (window),
|
||||||
|
m_device (device),
|
||||||
m_context (device->createContext()) {
|
m_context (device->createContext()) {
|
||||||
|
|
||||||
// Create Vulkan surface for the window
|
|
||||||
HINSTANCE instance = reinterpret_cast<HINSTANCE>(
|
|
||||||
GetWindowLongPtr(window, GWLP_HINSTANCE));
|
|
||||||
|
|
||||||
m_surface = m_device->adapter()->createSurface(instance, window);
|
|
||||||
|
|
||||||
// Reset options for the swap chain itself. We will
|
// Reset options for the swap chain itself. We will
|
||||||
// create a swap chain object before presentation.
|
// create a swap chain object before presentation.
|
||||||
m_options.preferredSurfaceFormat = { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
m_options.preferredSurfaceFormat = { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||||
@ -275,27 +270,52 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxgiVkPresenter::RecreateSwapchain(const DxvkSwapchainProperties* pOptions) {
|
void DxgiVkPresenter::SetGammaControl(
|
||||||
|
const DXGI_VK_GAMMA_CURVE* pGammaCurve) {
|
||||||
|
m_context->beginRecording(
|
||||||
|
m_device->createCommandList());
|
||||||
|
|
||||||
|
m_context->updateImage(m_gammaTexture,
|
||||||
|
VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
|
||||||
|
VkOffset3D { 0, 0, 0 },
|
||||||
|
VkExtent3D { DXGI_VK_GAMMA_CP_COUNT, 1, 1 },
|
||||||
|
pGammaCurve, 0, 0);
|
||||||
|
|
||||||
|
m_device->submitCommandList(
|
||||||
|
m_context->endRecording(),
|
||||||
|
nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxgiVkPresenter::RecreateSwapchain(DXGI_FORMAT Format, VkPresentModeKHR PresentMode, VkExtent2D WindowSize) {
|
||||||
|
if (m_surface == nullptr)
|
||||||
|
m_surface = CreateSurface();
|
||||||
|
|
||||||
|
DxvkSwapchainProperties options;
|
||||||
|
options.preferredSurfaceFormat = PickSurfaceFormat(Format);
|
||||||
|
options.preferredPresentMode = PickPresentMode(PresentMode);
|
||||||
|
options.preferredBufferSize = WindowSize;
|
||||||
|
|
||||||
const bool doRecreate =
|
const bool doRecreate =
|
||||||
pOptions->preferredSurfaceFormat.format != m_options.preferredSurfaceFormat.format
|
options.preferredSurfaceFormat.format != m_options.preferredSurfaceFormat.format
|
||||||
|| pOptions->preferredSurfaceFormat.colorSpace != m_options.preferredSurfaceFormat.colorSpace
|
|| options.preferredSurfaceFormat.colorSpace != m_options.preferredSurfaceFormat.colorSpace
|
||||||
|| pOptions->preferredPresentMode != m_options.preferredPresentMode
|
|| options.preferredPresentMode != m_options.preferredPresentMode
|
||||||
|| pOptions->preferredBufferSize.width != m_options.preferredBufferSize.width
|
|| options.preferredBufferSize.width != m_options.preferredBufferSize.width
|
||||||
|| pOptions->preferredBufferSize.height != m_options.preferredBufferSize.height;
|
|| options.preferredBufferSize.height != m_options.preferredBufferSize.height;
|
||||||
|
|
||||||
if (doRecreate) {
|
if (doRecreate) {
|
||||||
Logger::info(str::format(
|
Logger::info(str::format(
|
||||||
"DxgiVkPresenter: Recreating swap chain: ",
|
"DxgiVkPresenter: Recreating swap chain: ",
|
||||||
"\n Format: ", pOptions->preferredSurfaceFormat.format,
|
"\n Format: ", options.preferredSurfaceFormat.format,
|
||||||
"\n Present mode: ", pOptions->preferredPresentMode,
|
"\n Present mode: ", options.preferredPresentMode,
|
||||||
"\n Buffer size: ", pOptions->preferredBufferSize.width, "x", pOptions->preferredBufferSize.height));
|
"\n Buffer size: ", options.preferredBufferSize.width, "x", options.preferredBufferSize.height));
|
||||||
|
|
||||||
if (m_swapchain == nullptr)
|
if (m_swapchain == nullptr)
|
||||||
m_swapchain = m_device->createSwapchain(m_surface, *pOptions);
|
m_swapchain = m_device->createSwapchain(m_surface, options);
|
||||||
else
|
else
|
||||||
m_swapchain->changeProperties(*pOptions);
|
m_swapchain->changeProperties(options);
|
||||||
|
|
||||||
m_options = *pOptions;
|
m_options = options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,20 +359,11 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxgiVkPresenter::SetGammaControl(
|
Rc<DxvkSurface> DxgiVkPresenter::CreateSurface() {
|
||||||
const DXGI_VK_GAMMA_CURVE* pGammaCurve) {
|
HINSTANCE instance = reinterpret_cast<HINSTANCE>(
|
||||||
m_context->beginRecording(
|
GetWindowLongPtr(m_window, GWLP_HINSTANCE));
|
||||||
m_device->createCommandList());
|
|
||||||
|
|
||||||
m_context->updateImage(m_gammaTexture,
|
return m_device->adapter()->createSurface(instance, m_window);
|
||||||
VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
|
|
||||||
VkOffset3D { 0, 0, 0 },
|
|
||||||
VkExtent3D { DXGI_VK_GAMMA_CP_COUNT, 1, 1 },
|
|
||||||
pGammaCurve, 0, 0);
|
|
||||||
|
|
||||||
m_device->submitCommandList(
|
|
||||||
m_context->endRecording(),
|
|
||||||
nullptr, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,28 +100,14 @@ namespace dxvk {
|
|||||||
* Only actually recreates the swap chain object
|
* Only actually recreates the swap chain object
|
||||||
* if any of the properties have changed. If no
|
* if any of the properties have changed. If no
|
||||||
* properties have changed, this is a no-op.
|
* properties have changed, this is a no-op.
|
||||||
* \param [in] options New swap chain options
|
* \param [in] Format New surface format
|
||||||
|
* \param [in] PresentMode Present mode
|
||||||
|
* \param [in] WindowSize Window size
|
||||||
*/
|
*/
|
||||||
void RecreateSwapchain(
|
void RecreateSwapchain(
|
||||||
const DxvkSwapchainProperties* pOptions);
|
DXGI_FORMAT Format,
|
||||||
|
VkPresentModeKHR PresentMode,
|
||||||
/**
|
VkExtent2D WindowSize);
|
||||||
* \brief Picks a surface format based on a DXGI format
|
|
||||||
*
|
|
||||||
* This will return a supported format that, if possible,
|
|
||||||
* has properties similar to those of the DXGI format.
|
|
||||||
* \param [in] fmt The DXGI format
|
|
||||||
* \returns The Vulkan format
|
|
||||||
*/
|
|
||||||
VkSurfaceFormatKHR PickSurfaceFormat(DXGI_FORMAT Fmt) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Picks a supported present mode
|
|
||||||
*
|
|
||||||
* \param [in] preferred Preferred present mode
|
|
||||||
* \returns An actually supported present mode
|
|
||||||
*/
|
|
||||||
VkPresentModeKHR PickPresentMode(VkPresentModeKHR Preferred) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Sets gamma curve
|
* \brief Sets gamma curve
|
||||||
@ -142,6 +128,8 @@ namespace dxvk {
|
|||||||
GammaTex = 3,
|
GammaTex = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HWND m_window;
|
||||||
|
|
||||||
Rc<DxvkDevice> m_device;
|
Rc<DxvkDevice> m_device;
|
||||||
Rc<DxvkContext> m_context;
|
Rc<DxvkContext> m_context;
|
||||||
|
|
||||||
@ -164,6 +152,12 @@ namespace dxvk {
|
|||||||
DxvkBlendMode m_blendMode;
|
DxvkBlendMode m_blendMode;
|
||||||
DxvkSwapchainProperties m_options;
|
DxvkSwapchainProperties m_options;
|
||||||
|
|
||||||
|
VkSurfaceFormatKHR PickSurfaceFormat(DXGI_FORMAT Fmt) const;
|
||||||
|
|
||||||
|
VkPresentModeKHR PickPresentMode(VkPresentModeKHR Preferred) const;
|
||||||
|
|
||||||
|
Rc<DxvkSurface> CreateSurface();
|
||||||
|
|
||||||
Rc<DxvkSampler> CreateSampler(
|
Rc<DxvkSampler> CreateSampler(
|
||||||
VkFilter Filter,
|
VkFilter Filter,
|
||||||
VkSamplerAddressMode AddressMode);
|
VkSamplerAddressMode AddressMode);
|
||||||
|
@ -306,15 +306,11 @@ namespace dxvk {
|
|||||||
// up vertical synchronization properly, but also apply
|
// up vertical synchronization properly, but also apply
|
||||||
// changes that were made to the window size even if the
|
// changes that were made to the window size even if the
|
||||||
// Vulkan swap chain itself remains valid.
|
// Vulkan swap chain itself remains valid.
|
||||||
DxvkSwapchainProperties swapchainProps;
|
VkPresentModeKHR presentMode = SyncInterval == 0
|
||||||
swapchainProps.preferredSurfaceFormat
|
? VK_PRESENT_MODE_IMMEDIATE_KHR
|
||||||
= m_presenter->PickSurfaceFormat(m_desc.Format);
|
: VK_PRESENT_MODE_FIFO_KHR;
|
||||||
swapchainProps.preferredPresentMode = SyncInterval == 0
|
|
||||||
? m_presenter->PickPresentMode(VK_PRESENT_MODE_IMMEDIATE_KHR)
|
|
||||||
: m_presenter->PickPresentMode(VK_PRESENT_MODE_FIFO_KHR);
|
|
||||||
swapchainProps.preferredBufferSize = GetWindowSize();
|
|
||||||
|
|
||||||
m_presenter->RecreateSwapchain(&swapchainProps);
|
m_presenter->RecreateSwapchain(m_desc.Format, presentMode, GetWindowSize());
|
||||||
m_presenter->PresentImage();
|
m_presenter->PresentImage();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
} catch (const DxvkError& err) {
|
} catch (const DxvkError& err) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user