1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-07 16:54:14 +01:00

[dxvk] Import swap chain images from the back-end

This commit is contained in:
Philip Rebohle 2025-01-12 17:29:53 +01:00 committed by Philip Rebohle
parent 073806df7c
commit ab9646551f
6 changed files with 66 additions and 165 deletions

View File

@ -387,12 +387,11 @@ namespace dxvk {
return DXGI_STATUS_OCCLUDED;
// Presentation semaphores and WSI swap chain image
PresenterInfo info = m_presenter->info();
PresenterSync sync;
uint32_t imageIndex = 0;
Rc<DxvkImage> backBuffer;
VkResult status = m_presenter->acquireNextImage(sync, imageIndex);
VkResult status = m_presenter->acquireNextImage(sync, backBuffer);
while (status != VK_SUCCESS) {
RecreateSwapChain();
@ -400,8 +399,7 @@ namespace dxvk {
if (!m_presenter->hasSwapChain())
return DXGI_STATUS_OCCLUDED;
info = m_presenter->info();
status = m_presenter->acquireNextImage(sync, imageIndex);
status = m_presenter->acquireNextImage(sync, backBuffer);
if (status == VK_SUBOPTIMAL_KHR)
break;
@ -418,11 +416,21 @@ namespace dxvk {
// have to synchronize with it first.
m_presentStatus.result = VK_NOT_READY;
DxvkImageViewKey viewInfo = { };
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
viewInfo.format = backBuffer->info().format;
viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.mipIndex = 0u;
viewInfo.mipCount = 1u;
viewInfo.layerIndex = 0u;
viewInfo.layerCount = 1u;
immediateContext->EmitCs([
cPresentStatus = &m_presentStatus,
cDevice = m_device,
cBlitter = m_blitter,
cBackBuffer = m_imageViews.at(imageIndex),
cBackBuffer = backBuffer->createView(viewInfo),
cSwapImage = GetBackBufferView(),
cSync = sync,
cHud = m_hud,
@ -507,8 +515,6 @@ namespace dxvk {
if (vr)
throw DxvkError(str::format("D3D11SwapChain: Failed to recreate swap chain: ", vr));
CreateRenderTargetViews();
}
@ -539,48 +545,6 @@ namespace dxvk {
}
void D3D11SwapChain::CreateRenderTargetViews() {
PresenterInfo info = m_presenter->info();
m_imageViews.clear();
m_imageViews.resize(info.imageCount);
DxvkImageCreateInfo imageInfo;
imageInfo.type = VK_IMAGE_TYPE_2D;
imageInfo.format = info.format.format;
imageInfo.flags = 0;
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 };
imageInfo.numLayers = 1;
imageInfo.mipLevels = 1;
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imageInfo.stages = 0;
imageInfo.access = 0;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
imageInfo.shared = VK_TRUE;
imageInfo.debugName = "Swap image";
DxvkImageViewKey viewInfo;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = info.format.format;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
for (uint32_t i = 0; i < info.imageCount; i++) {
VkImage imageHandle = m_presenter->getImage(i).image;
Rc<DxvkImage> image = m_device->importImage(imageInfo,
imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_imageViews[i] = image->createView(viewInfo);
}
}
void D3D11SwapChain::CreateBackBuffers() {
// Explicitly destroy current swap image before
// creating a new one to free up resources

View File

@ -113,8 +113,6 @@ namespace dxvk {
small_vector<Com<D3D11Texture2D, false>, 4> m_backBuffers;
DxvkSubmitStatus m_presentStatus;
std::vector<Rc<DxvkImageView>> m_imageViews;
uint64_t m_frameId = DXGI_MAX_SWAP_CHAIN_BUFFERS;
uint32_t m_frameLatency = DefaultFrameLatency;
uint32_t m_frameLatencyCap = 0;
@ -147,8 +145,6 @@ namespace dxvk {
void CreatePresenter();
void CreateRenderTargetViews();
void CreateBackBuffers();
void CreateBlitter();

View File

@ -833,15 +833,15 @@ namespace dxvk {
PresenterInfo info = m_wctx->presenter->info();
PresenterSync sync = { };
uint32_t imageIndex = 0;
Rc<DxvkImage> backBuffer;
VkResult status = m_wctx->presenter->acquireNextImage(sync, imageIndex);
VkResult status = m_wctx->presenter->acquireNextImage(sync, backBuffer);
while (status != VK_SUCCESS) {
RecreateSwapChain();
info = m_wctx->presenter->info();
status = m_wctx->presenter->acquireNextImage(sync, imageIndex);
status = m_wctx->presenter->acquireNextImage(sync, backBuffer);
if (status == VK_SUBOPTIMAL_KHR)
break;
@ -868,6 +868,16 @@ namespace dxvk {
// have to synchronize with it first.
m_presentStatus.result = VK_NOT_READY;
DxvkImageViewKey viewInfo;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
viewInfo.format = backBuffer->info().format;
viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.mipIndex = 0u;
viewInfo.mipCount = 1u;
viewInfo.layerIndex = 0u;
viewInfo.layerCount = 1u;
m_parent->EmitCs([
cPresentStatus = &m_presentStatus,
cDevice = m_device,
@ -876,7 +886,7 @@ namespace dxvk {
cColorSpace = m_colorspace,
cSrcView = swapImageView,
cSrcRect = srcRect,
cDstView = m_wctx->imageViews.at(imageIndex),
cDstView = backBuffer->createView(viewInfo),
cDstRect = dstRect,
cRepeat = i,
cSync = sync,
@ -948,8 +958,6 @@ namespace dxvk {
if (vr)
throw DxvkError(str::format("D3D9SwapChainEx: Failed to recreate swap chain: ", vr));
CreateRenderTargetViews();
}
@ -980,47 +988,6 @@ namespace dxvk {
}
void D3D9SwapChainEx::CreateRenderTargetViews() {
PresenterInfo info = m_wctx->presenter->info();
m_wctx->imageViews.clear();
m_wctx->imageViews.resize(info.imageCount);
DxvkImageCreateInfo imageInfo;
imageInfo.type = VK_IMAGE_TYPE_2D;
imageInfo.format = info.format.format;
imageInfo.flags = 0;
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 };
imageInfo.numLayers = 1;
imageInfo.mipLevels = 1;
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imageInfo.stages = 0;
imageInfo.access = 0;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
imageInfo.shared = VK_TRUE;
DxvkImageViewKey viewInfo;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = info.format.format;
viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
for (uint32_t i = 0; i < info.imageCount; i++) {
VkImage imageHandle = m_wctx->presenter->getImage(i).image;
Rc<DxvkImage> image = m_device->importImage(imageInfo,
imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_wctx->imageViews[i] = image->createView(viewInfo);
}
}
void D3D9SwapChainEx::DestroyBackBuffers() {
for (auto& backBuffer : m_backBuffers)
backBuffer->ClearContainer();

View File

@ -52,7 +52,6 @@ namespace dxvk {
struct D3D9WindowContext {
Rc<Presenter> presenter;
std::vector<Rc<DxvkImageView>> imageViews;
uint64_t frameId = D3D9DeviceEx::MaxFrameLatency;
Rc<sync::Fence> frameLatencySignal;
@ -199,8 +198,6 @@ namespace dxvk {
void CreatePresenter();
void CreateRenderTargetViews();
HRESULT CreateBackBuffers(
uint32_t NumBackBuffers,
DWORD Flags);

View File

@ -51,12 +51,7 @@ namespace dxvk {
}
PresenterImage Presenter::getImage(uint32_t index) const {
return m_images.at(index);
}
VkResult Presenter::acquireNextImage(PresenterSync& sync, uint32_t& index) {
VkResult Presenter::acquireNextImage(PresenterSync& sync, Rc<DxvkImage>& image) {
PresenterSync& semaphores = m_semaphores.at(m_frameIndex);
sync = semaphores;
@ -72,7 +67,7 @@ namespace dxvk {
if (m_acquireStatus != VK_SUCCESS && m_acquireStatus != VK_SUBOPTIMAL_KHR)
return m_acquireStatus;
index = m_imageIndex;
image = m_images.at(m_imageIndex);
return m_acquireStatus;
}
@ -362,25 +357,25 @@ namespace dxvk {
// Update actual image count
m_info.imageCount = images.size();
m_images.resize(m_info.imageCount);
for (uint32_t i = 0; i < m_info.imageCount; i++) {
m_images[i].image = images[i];
std::string debugName = str::format("Vulkan swap image ", i);
VkImageViewCreateInfo viewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
viewInfo.image = images[i];
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = m_info.format.format;
viewInfo.components = VkComponentMapping {
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
viewInfo.subresourceRange = {
VK_IMAGE_ASPECT_COLOR_BIT,
0, 1, 0, 1 };
if ((status = m_vkd->vkCreateImageView(m_vkd->device(),
&viewInfo, nullptr, &m_images[i].view)))
return status;
DxvkImageCreateInfo imageInfo = { };
imageInfo.type = VK_IMAGE_TYPE_2D;
imageInfo.format = swapInfo.imageFormat;
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
imageInfo.extent = { swapInfo.imageExtent.width, swapInfo.imageExtent.height, 1u };
imageInfo.numLayers = swapInfo.imageArrayLayers;
imageInfo.mipLevels = 1u;
imageInfo.usage = swapInfo.imageUsage;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
imageInfo.shared = VK_TRUE;
imageInfo.debugName = debugName.c_str();
m_images.push_back(m_device->importImage(imageInfo, images[i],
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
}
// Create one set of semaphores per swap image, as well as a fence
@ -678,9 +673,6 @@ namespace dxvk {
for (auto& sem : m_semaphores)
waitForSwapchainFence(sem);
for (const auto& img : m_images)
m_vkd->vkDestroyImageView(m_vkd->device(), img.view, nullptr);
for (const auto& sem : m_semaphores) {
m_vkd->vkDestroySemaphore(m_vkd->device(), sem.acquire, nullptr);
m_vkd->vkDestroySemaphore(m_vkd->device(), sem.present, nullptr);

View File

@ -16,6 +16,7 @@
#include "../vulkan/vulkan_loader.h"
#include "dxvk_format.h"
#include "dxvk_image.h"
namespace dxvk {
@ -51,14 +52,6 @@ namespace dxvk {
uint32_t syncInterval;
};
/**
* \brief Swap image and view
*/
struct PresenterImage {
VkImage image = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
};
/**
* \brief Presenter semaphores
*
@ -108,16 +101,6 @@ namespace dxvk {
*/
PresenterInfo info() const;
/**
* \brief Retrieves image by index
*
* Can be used to create per-image objects.
* \param [in] index Image index
* \returns Image handle
*/
PresenterImage getImage(
uint32_t index) const;
/**
* \brief Acquires next image
*
@ -126,12 +109,12 @@ namespace dxvk {
* must be recreated and a new image must
* be acquired before proceeding.
* \param [out] sync Synchronization semaphores
* \param [out] index Acquired image index
* \param [out] image Acquired swap chain image
* \returns Status of the operation
*/
VkResult acquireNextImage(
PresenterSync& sync,
uint32_t& index);
Rc<DxvkImage>& image);
/**
* \brief Presents current image
@ -222,32 +205,31 @@ namespace dxvk {
private:
Rc<DxvkDevice> m_device;
Rc<sync::Signal> m_signal;
Rc<DxvkDevice> m_device;
Rc<sync::Signal> m_signal;
Rc<vk::InstanceFn> m_vki;
Rc<vk::DeviceFn> m_vkd;
Rc<vk::InstanceFn> m_vki;
Rc<vk::DeviceFn> m_vkd;
PresenterInfo m_info = { };
PresenterSurfaceProc m_surfaceProc;
PresenterInfo m_info = { };
PresenterSurfaceProc m_surfaceProc;
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
VkFullScreenExclusiveEXT m_fullscreenMode = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT;
VkFullScreenExclusiveEXT m_fullscreenMode = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT;
std::vector<PresenterImage> m_images;
std::vector<Rc<DxvkImage>> m_images;
std::vector<PresenterSync> m_semaphores;
std::vector<VkPresentModeKHR> m_dynamicModes;
uint32_t m_imageIndex = 0;
uint32_t m_frameIndex = 0;
uint32_t m_imageIndex = 0;
uint32_t m_frameIndex = 0;
VkResult m_acquireStatus = VK_NOT_READY;
FpsLimiter m_fpsLimiter;
VkResult m_acquireStatus = VK_NOT_READY;
alignas(CACHE_LINE_SIZE)
dxvk::mutex m_frameMutex;
dxvk::condition_variable m_frameCond;
dxvk::thread m_frameThread;
@ -255,6 +237,9 @@ namespace dxvk {
std::atomic<uint64_t> m_lastFrameId = { 0ull };
alignas(CACHE_LINE_SIZE)
FpsLimiter m_fpsLimiter;
VkResult createSwapChain(
const PresenterDesc& desc);