1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +01:00

[d3d11] Implement sequential swap effects

This commit is contained in:
Philip Rebohle 2024-10-02 15:24:09 +02:00 committed by Philip Rebohle
parent c9ec2eeab2
commit a278d6bf1d
2 changed files with 78 additions and 37 deletions

View File

@ -66,7 +66,7 @@ namespace dxvk {
m_frameLatencyCap(pDevice->GetOptions()->maxFrameLatency) {
CreateFrameLatencyEvent();
CreatePresenter();
CreateBackBuffer();
CreateBackBuffers();
CreateBlitter();
CreateHud();
@ -140,12 +140,12 @@ namespace dxvk {
void** ppBuffer) {
InitReturnPtr(ppBuffer);
if (BufferId > 0) {
Logger::err("D3D11: GetImage: BufferId > 0 not supported");
if (BufferId >= m_backBuffers.size()) {
Logger::err("D3D11: GetImage: Invalid buffer ID");
return DXGI_ERROR_UNSUPPORTED;
}
return m_backBuffer->QueryInterface(riid, ppBuffer);
return m_backBuffers[BufferId]->QueryInterface(riid, ppBuffer);
}
@ -184,7 +184,7 @@ namespace dxvk {
|| m_desc.Flags != pDesc->Flags;
m_desc = *pDesc;
CreateBackBuffer();
CreateBackBuffers();
return S_OK;
}
@ -356,6 +356,23 @@ namespace dxvk {
}
Rc<DxvkImageView> D3D11SwapChain::GetBackBufferView() {
Rc<DxvkImage> image = GetCommonTexture(m_backBuffers[0].ptr())->GetImage();
DxvkImageViewKey key;
key.viewType = VK_IMAGE_VIEW_TYPE_2D;
key.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
key.format = image->info().format;
key.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
key.mipIndex = 0u;
key.mipCount = 1u;
key.layerIndex = 0u;
key.layerCount = 1u;
return image->createView(key);
}
HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) {
// Flush pending rendering commands before
auto immediateContext = m_parent->GetContext();
@ -406,7 +423,7 @@ namespace dxvk {
cDevice = m_device,
cBlitter = m_blitter,
cBackBuffer = m_imageViews.at(imageIndex),
cSwapImage = m_swapImageView,
cSwapImage = GetBackBufferView(),
cSync = sync,
cHud = m_hud,
cPresenter = m_presenter,
@ -437,11 +454,33 @@ namespace dxvk {
cFrameId, cPresentStatus);
});
if (m_backBuffers.size() > 1u)
RotateBackBuffers(immediateContext);
immediateContext->FlushCsChunk();
return S_OK;
}
void D3D11SwapChain::RotateBackBuffers(D3D11ImmediateContext* ctx) {
small_vector<Rc<DxvkImage>, 4> images;
for (uint32_t i = 0; i < m_backBuffers.size(); i++)
images.push_back(GetCommonTexture(m_backBuffers[i].ptr())->GetImage());
ctx->EmitCs([
cImages = std::move(images)
] (DxvkContext* ctx) {
auto allocation = cImages[0]->getAllocation();
for (size_t i = 0u; i + 1 < cImages.size(); i++)
ctx->invalidateImage(cImages[i], cImages[i + 1]->getAllocation());
ctx->invalidateImage(cImages[cImages.size() - 1u], std::move(allocation));
});
}
void D3D11SwapChain::SynchronizePresent() {
// Recreate swap chain if the previous present call failed
VkResult status = m_device->waitForSubmission(&m_presentStatus);
@ -555,12 +594,14 @@ namespace dxvk {
}
void D3D11SwapChain::CreateBackBuffer() {
void D3D11SwapChain::CreateBackBuffers() {
// Explicitly destroy current swap image before
// creating a new one to free up resources
m_swapImage = nullptr;
m_swapImageView = nullptr;
m_backBuffer = nullptr;
m_backBuffers.clear();
bool sequential = m_desc.SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL ||
m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
uint32_t backBufferCount = sequential ? m_desc.BufferCount : 1u;
// Create new back buffer
D3D11_COMMON_TEXTURE_DESC desc;
@ -591,34 +632,32 @@ namespace dxvk {
DXGI_USAGE dxgiUsage = DXGI_USAGE_BACK_BUFFER;
if (m_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD
|| m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
dxgiUsage |= DXGI_USAGE_DISCARD_ON_PRESENT;
for (uint32_t i = 0; i < backBufferCount; i++) {
if (m_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD
|| m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
dxgiUsage |= DXGI_USAGE_DISCARD_ON_PRESENT;
m_backBuffer = new D3D11Texture2D(m_parent, this, &desc, dxgiUsage);
m_swapImage = GetCommonTexture(m_backBuffer.ptr())->GetImage();
m_backBuffers.push_back(new D3D11Texture2D(
m_parent, this, &desc, dxgiUsage));
// Create an image view that allows the
// image to be bound as a shader resource.
DxvkImageViewKey viewInfo;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = m_swapImage->info().format;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.mipIndex = 0;
viewInfo.mipCount = 1;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
m_swapImageView = m_swapImage->createView(viewInfo);
// Initialize the image so that we can use it. Clearing
dxgiUsage |= DXGI_USAGE_READ_ONLY;
}
small_vector<Rc<DxvkImage>, 4> images;
for (uint32_t i = 0; i < backBufferCount; i++)
images.push_back(GetCommonTexture(m_backBuffers[i].ptr())->GetImage());
// Initialize images so that we can use them. Clearing
// to black prevents garbled output for the first frame.
m_parent->GetContext()->InjectCs([
cSwapImage = m_swapImage
cImages = std::move(images)
] (DxvkContext* ctx) {
ctx->initImage(cSwapImage,
cSwapImage->getAvailableSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED);
for (size_t i = 0; i < cImages.size(); i++) {
ctx->initImage(cImages[i],
cImages[i]->getAvailableSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED);
}
});
}

View File

@ -106,13 +106,11 @@ namespace dxvk {
Rc<DxvkDevice> m_device;
Rc<Presenter> m_presenter;
Rc<DxvkImage> m_swapImage;
Rc<DxvkImageView> m_swapImageView;
Rc<DxvkSwapchainBlitter> m_blitter;
Rc<hud::Hud> m_hud;
Com<D3D11Texture2D, false> m_backBuffer;
small_vector<Com<D3D11Texture2D, false>, 4> m_backBuffers;
DxvkSubmitStatus m_presentStatus;
std::vector<Rc<DxvkImageView>> m_imageViews;
@ -135,8 +133,12 @@ namespace dxvk {
dxvk::mutex m_frameStatisticsLock;
DXGI_VK_FRAME_STATISTICS m_frameStatistics = { };
Rc<DxvkImageView> GetBackBufferView();
HRESULT PresentImage(UINT SyncInterval);
void RotateBackBuffers(D3D11ImmediateContext* ctx);
void SynchronizePresent();
void RecreateSwapChain();
@ -149,7 +151,7 @@ namespace dxvk {
void CreateRenderTargetViews();
void CreateBackBuffer();
void CreateBackBuffers();
void CreateBlitter();