mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +01:00
[d3d11] Implement DXGI_SWAP_EFFECT_SEQUENTIAL and FLIP_SEQUENTIAL
Requires sparse since we have no other means to swap the backing image.
This commit is contained in:
parent
53a68635b2
commit
79f6239df3
@ -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(str::format("D3D11: Invalid buffer index: ", BufferId));
|
||||
return DXGI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return m_backBuffer->QueryInterface(riid, ppBuffer);
|
||||
return m_backBuffers[BufferId]->QueryInterface(riid, ppBuffer);
|
||||
}
|
||||
|
||||
|
||||
@ -396,7 +396,10 @@ namespace dxvk {
|
||||
|
||||
if (m_hud != nullptr)
|
||||
m_hud->render(m_context, info.format, info.imageExtent);
|
||||
|
||||
|
||||
if (!SyncInterval || i == SyncInterval - 1)
|
||||
RotateBackBuffer();
|
||||
|
||||
SubmitPresent(immediateContext, sync, i);
|
||||
}
|
||||
|
||||
@ -559,11 +562,25 @@ namespace dxvk {
|
||||
|
||||
|
||||
void D3D11SwapChain::CreateBackBuffer() {
|
||||
bool sequentialPresent = false;
|
||||
|
||||
if (IsSequentialSwapChain()) {
|
||||
if (!(sequentialPresent = SupportsSparseImages())) {
|
||||
Logger::warn("Sequential present mode requeted, but sparse images not supported"
|
||||
"by the Vulkan implementation. Falling back to Discard semantics.");
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly destroy current swap image before
|
||||
// creating a new one to free up resources
|
||||
m_swapImage = nullptr;
|
||||
m_swapImageView = nullptr;
|
||||
m_backBuffer = nullptr;
|
||||
m_swapImages.clear();
|
||||
m_backBuffers.clear();
|
||||
m_swapImageView = nullptr;
|
||||
|
||||
uint32_t bufferCount = 1u;
|
||||
|
||||
if (sequentialPresent)
|
||||
bufferCount = m_desc.BufferCount;
|
||||
|
||||
// Create new back buffer
|
||||
D3D11_COMMON_TEXTURE_DESC desc;
|
||||
@ -592,27 +609,47 @@ namespace dxvk {
|
||||
if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE)
|
||||
desc.MiscFlags |= D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
|
||||
|
||||
if (sequentialPresent)
|
||||
desc.MiscFlags |= D3D11_RESOURCE_MISC_TILED;
|
||||
|
||||
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;
|
||||
|
||||
m_backBuffer = new D3D11Texture2D(m_parent, this, &desc, dxgiUsage);
|
||||
m_swapImage = GetCommonTexture(m_backBuffer.ptr())->GetImage();
|
||||
for (uint32_t i = 0; i < bufferCount; i++) {
|
||||
m_backBuffers.push_back(new D3D11Texture2D(m_parent, this, &desc, dxgiUsage));
|
||||
m_swapImages.push_back(GetCommonTexture(m_backBuffers.back().ptr())->GetImage());
|
||||
|
||||
dxgiUsage |= DXGI_USAGE_READ_ONLY;
|
||||
}
|
||||
|
||||
// If necessary, create a sparse page allocator
|
||||
m_sparseFrameIndex = 0;
|
||||
|
||||
if (sequentialPresent) {
|
||||
m_sparsePagesPerImage = m_swapImages.front()->getSparsePageTable()->getPageCount();
|
||||
|
||||
m_sparseAllocator = m_device->createSparsePageAllocator();
|
||||
m_sparseAllocator->setCapacity(m_sparsePagesPerImage * bufferCount);
|
||||
} else {
|
||||
m_sparsePagesPerImage = 0;
|
||||
m_sparseAllocator = nullptr;
|
||||
}
|
||||
|
||||
// Create an image view that allows the
|
||||
// image to be bound as a shader resource.
|
||||
DxvkImageViewCreateInfo viewInfo;
|
||||
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = m_swapImage->info().format;
|
||||
viewInfo.format = m_swapImages.front()->info().format;
|
||||
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.minLevel = 0;
|
||||
viewInfo.numLevels = 1;
|
||||
viewInfo.minLayer = 0;
|
||||
viewInfo.numLayers = 1;
|
||||
m_swapImageView = m_device->createImageView(m_swapImage, viewInfo);
|
||||
m_swapImageView = m_device->createImageView(m_swapImages.front(), viewInfo);
|
||||
|
||||
// Initialize the image so that we can use it. Clearing
|
||||
// to black prevents garbled output for the first frame.
|
||||
@ -626,8 +663,30 @@ namespace dxvk {
|
||||
m_context->beginRecording(
|
||||
m_device->createCommandList());
|
||||
|
||||
m_context->initImage(m_swapImage,
|
||||
subresources, VK_IMAGE_LAYOUT_UNDEFINED);
|
||||
for (uint32_t i = 0; i < m_swapImages.size(); i++) {
|
||||
if (sequentialPresent) {
|
||||
DxvkSparseBindInfo sparseBind;
|
||||
sparseBind.dstResource = m_swapImages[i];
|
||||
sparseBind.srcAllocator = m_sparseAllocator;
|
||||
|
||||
for (uint32_t j = 0; j < m_sparsePagesPerImage; j++) {
|
||||
auto& bind = sparseBind.binds.emplace_back();
|
||||
bind.mode = DxvkSparseBindMode::Bind;
|
||||
bind.srcPage = j + i * m_sparsePagesPerImage;
|
||||
bind.dstPage = j;
|
||||
}
|
||||
|
||||
m_context->updatePageTable(sparseBind,
|
||||
DxvkSparseBindFlag::SkipSynchronization);
|
||||
m_context->initSparseImage(m_swapImages[i]);
|
||||
|
||||
Rc<DxvkImageView> view = m_device->createImageView(m_swapImages.front(), viewInfo);
|
||||
m_context->clearRenderTarget(view, VK_IMAGE_ASPECT_COLOR_BIT, VkClearValue());
|
||||
} else {
|
||||
m_context->initImage(m_swapImages[i],
|
||||
subresources, VK_IMAGE_LAYOUT_UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
m_device->submitCommandList(
|
||||
m_context->endRecording(),
|
||||
@ -738,6 +797,51 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void D3D11SwapChain::RotateBackBuffer() {
|
||||
uint32_t bufferCount = m_swapImages.size();
|
||||
|
||||
if (bufferCount < 2)
|
||||
return;
|
||||
|
||||
m_sparseFrameIndex += 1;
|
||||
m_sparseFrameIndex %= bufferCount;
|
||||
|
||||
for (uint32_t i = 0; i < bufferCount; i++) {
|
||||
uint32_t firstImage = (m_sparseFrameIndex + i) % bufferCount;
|
||||
|
||||
DxvkSparseBindInfo sparseBind;
|
||||
sparseBind.dstResource = m_swapImages[i];
|
||||
sparseBind.srcAllocator = m_sparseAllocator;
|
||||
|
||||
for (uint32_t j = 0; j < m_sparsePagesPerImage; j++) {
|
||||
auto& bind = sparseBind.binds.emplace_back();
|
||||
bind.mode = DxvkSparseBindMode::Bind;
|
||||
bind.srcPage = j + firstImage * m_sparsePagesPerImage;
|
||||
bind.dstPage = j;
|
||||
}
|
||||
|
||||
m_context->updatePageTable(sparseBind, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool D3D11SwapChain::IsSequentialSwapChain() const {
|
||||
return m_desc.SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL
|
||||
|| m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
}
|
||||
|
||||
|
||||
bool D3D11SwapChain::SupportsSparseImages() const {
|
||||
const auto& properties = m_device->properties().core.properties;
|
||||
const auto& features = m_device->features().core.features;
|
||||
|
||||
return features.sparseBinding
|
||||
&& features.sparseResidencyImage2D
|
||||
&& features.sparseResidencyAliased
|
||||
&& properties.sparseProperties.residencyStandard2DBlockShape;
|
||||
}
|
||||
|
||||
|
||||
std::string D3D11SwapChain::GetApiName() const {
|
||||
Com<IDXGIDXVKDevice> device;
|
||||
m_parent->QueryInterface(__uuidof(IDXGIDXVKDevice), reinterpret_cast<void**>(&device));
|
||||
|
@ -95,42 +95,46 @@ namespace dxvk {
|
||||
|
||||
Com<D3D11DXGIDevice, false> m_dxgiDevice;
|
||||
|
||||
D3D11Device* m_parent;
|
||||
Com<IDXGIVkSurfaceFactory> m_surfaceFactory;
|
||||
D3D11Device* m_parent;
|
||||
Com<IDXGIVkSurfaceFactory> m_surfaceFactory;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 m_desc;
|
||||
DXGI_SWAP_CHAIN_DESC1 m_desc;
|
||||
|
||||
Rc<DxvkDevice> m_device;
|
||||
Rc<DxvkContext> m_context;
|
||||
Rc<DxvkDevice> m_device;
|
||||
Rc<DxvkContext> m_context;
|
||||
|
||||
Rc<Presenter> m_presenter;
|
||||
Rc<Presenter> m_presenter;
|
||||
|
||||
Rc<DxvkImage> m_swapImage;
|
||||
Rc<DxvkImageView> m_swapImageView;
|
||||
Rc<DxvkSwapchainBlitter> m_blitter;
|
||||
uint32_t m_sparseFrameIndex = 0u;
|
||||
uint32_t m_sparsePagesPerImage = 0u;
|
||||
Rc<DxvkSparsePageAllocator> m_sparseAllocator;
|
||||
|
||||
Rc<hud::Hud> m_hud;
|
||||
std::vector<Rc<DxvkImage>> m_swapImages;
|
||||
Rc<DxvkImageView> m_swapImageView;
|
||||
Rc<DxvkSwapchainBlitter> m_blitter;
|
||||
|
||||
Com<D3D11Texture2D, false> m_backBuffer;
|
||||
DxvkSubmitStatus m_presentStatus;
|
||||
Rc<hud::Hud> m_hud;
|
||||
|
||||
std::vector<Com<D3D11Texture2D, false>> 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;
|
||||
HANDLE m_frameLatencyEvent = nullptr;
|
||||
Rc<sync::CallbackFence> m_frameLatencySignal;
|
||||
uint64_t m_frameId = DXGI_MAX_SWAP_CHAIN_BUFFERS;
|
||||
uint32_t m_frameLatency = DefaultFrameLatency;
|
||||
uint32_t m_frameLatencyCap = 0;
|
||||
HANDLE m_frameLatencyEvent = nullptr;
|
||||
Rc<sync::CallbackFence> m_frameLatencySignal;
|
||||
|
||||
bool m_dirty = true;
|
||||
bool m_dirty = true;
|
||||
|
||||
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
|
||||
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
||||
bool m_dirtyHdrMetadata = true;
|
||||
bool m_dirtyHdrMetadata = true;
|
||||
|
||||
dxvk::mutex m_frameStatisticsLock;
|
||||
DXGI_VK_FRAME_STATISTICS m_frameStatistics = { };
|
||||
dxvk::mutex m_frameStatisticsLock;
|
||||
DXGI_VK_FRAME_STATISTICS m_frameStatistics = { };
|
||||
|
||||
HRESULT PresentImage(UINT SyncInterval);
|
||||
|
||||
@ -172,6 +176,12 @@ namespace dxvk {
|
||||
|
||||
VkFullScreenExclusiveEXT PickFullscreenMode();
|
||||
|
||||
void RotateBackBuffer();
|
||||
|
||||
bool IsSequentialSwapChain() const;
|
||||
|
||||
bool SupportsSparseImages() const;
|
||||
|
||||
std::string GetApiName() const;
|
||||
|
||||
};
|
||||
|
@ -249,6 +249,10 @@ namespace dxvk {
|
||||
|
||||
if (imageInfo.sharing.mode == DxvkSharedHandleMode::Export)
|
||||
ExportImageInfo();
|
||||
|
||||
// Hide some internal flags as necessary
|
||||
if (DxgiUsage & DXGI_USAGE_BACK_BUFFER)
|
||||
m_desc.MiscFlags &= ~D3D11_RESOURCE_MISC_TILED;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user