QVulkanWindow: sync surface size logic with QRhi
The legacy QWindow convenience subclass does not have the robust logic that was later implemented for the Vulkan backend of QRhi. (i.e., never trust the QWindow; problem with QVulkanWindow is that it half-trusts those values still, which leads to the classic pixel-size-differs-by-one problem) Fixes: QTBUG-118568 Change-Id: I5f83999e86a9907efe08b38ca069bae20152a4e0 Reviewed-by: Andy Nichols <andy.nichols@qt.io> (cherry picked from commit 149f178d3fc01b84a92be63a7ba11529c7d769b5) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit daedbdbba7099479573e92ec555b309db41c7731) (cherry picked from commit f42e846810b54724f06b67b8a6a83f18faeee65b)
This commit is contained in:
parent
2b361aceb3
commit
e132f55acb
@ -1834,13 +1834,26 @@ void QVulkanWindowRenderer::logicalDeviceLost()
|
||||
{
|
||||
}
|
||||
|
||||
QSize QVulkanWindowPrivate::surfacePixelSize() const
|
||||
{
|
||||
Q_Q(const QVulkanWindow);
|
||||
VkSurfaceCapabilitiesKHR surfaceCaps = {};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDevs.at(physDevIndex), surface, &surfaceCaps);
|
||||
VkExtent2D bufferSize = surfaceCaps.currentExtent;
|
||||
if (bufferSize.width == uint32_t(-1)) {
|
||||
Q_ASSERT(bufferSize.height == uint32_t(-1));
|
||||
return q->size() * q->devicePixelRatio();
|
||||
}
|
||||
return QSize(int(bufferSize.width), int(bufferSize.height));
|
||||
}
|
||||
|
||||
void QVulkanWindowPrivate::beginFrame()
|
||||
{
|
||||
if (!swapChain || framePending)
|
||||
return;
|
||||
|
||||
Q_Q(QVulkanWindow);
|
||||
if (q->size() * q->devicePixelRatio() != swapChainImageSize) {
|
||||
if (swapChainImageSize != surfacePixelSize()) {
|
||||
recreateSwapChain();
|
||||
if (!swapChain)
|
||||
return;
|
||||
@ -2425,6 +2438,19 @@ VkFormat QVulkanWindow::depthStencilFormat() const
|
||||
This usually matches the size of the window, but may also differ in case
|
||||
\c vkGetPhysicalDeviceSurfaceCapabilitiesKHR reports a fixed size.
|
||||
|
||||
In addition, it has been observed on some platforms that the
|
||||
Vulkan-reported surface size is different with high DPI scaling active,
|
||||
meaning the QWindow-reported
|
||||
\l{QWindow::}{size()} multiplied with the \l{QWindow::}{devicePixelRatio()}
|
||||
was 1 pixel less or more when compared to the value returned from here,
|
||||
presumably due to differences in rounding. Rendering code should be aware
|
||||
of this, and any related rendering logic must be based in the value returned
|
||||
from here, never on the QWindow-reported size. Regardless of which pixel size
|
||||
is correct in theory, Vulkan rendering must only ever rely on the Vulkan
|
||||
API-reported surface size. Otherwise validation errors may occur, e.g. when
|
||||
setting the viewport, because the application-provided values may become
|
||||
out-of-bounds from Vulkan's perspective.
|
||||
|
||||
\note Calling this function is only valid from the invocation of
|
||||
QVulkanWindowRenderer::initSwapChainResources() up until
|
||||
QVulkanWindowRenderer::releaseSwapChainResources().
|
||||
|
@ -72,6 +72,7 @@ public:
|
||||
void init();
|
||||
void reset();
|
||||
bool createDefaultRenderPass();
|
||||
QSize surfacePixelSize() const;
|
||||
void recreateSwapChain();
|
||||
uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex);
|
||||
bool createTransientImage(VkFormat format, VkImageUsageFlags usage, VkImageAspectFlags aspectMask,
|
||||
|
Loading…
x
Reference in New Issue
Block a user