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:
parent
073806df7c
commit
ab9646551f
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user