rhi: Fix non-base level copy and readback wrt source size
When the source size is not explicitly specified, we take the entire subresource. However, just using the texture's size is wrong: when the source level in a copy or readback is not 0, the size for the corresponding mip level has to be used instead. This fixes occasional crashes with Metal in the autotest. Change-Id: I99f689feef93ec86dffdc9e82d6bfdaf5c1eb041 Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>bb10
parent
dd105fab8d
commit
59604405c9
|
|
@ -1416,15 +1416,16 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||
UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
|
||||
UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
|
||||
const QPoint dp = u.desc.destinationTopLeft();
|
||||
const QSize size = u.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize();
|
||||
const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
|
||||
const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
|
||||
const QPoint sp = u.desc.sourceTopLeft();
|
||||
D3D11_BOX srcBox;
|
||||
srcBox.left = UINT(sp.x());
|
||||
srcBox.top = UINT(sp.y());
|
||||
srcBox.front = 0;
|
||||
// back, right, bottom are exclusive
|
||||
srcBox.right = srcBox.left + UINT(size.width());
|
||||
srcBox.bottom = srcBox.top + UINT(size.height());
|
||||
srcBox.right = srcBox.left + UINT(copySize.width());
|
||||
srcBox.bottom = srcBox.top + UINT(copySize.height());
|
||||
srcBox.back = 1;
|
||||
QD3D11CommandBuffer::Command cmd;
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes;
|
||||
|
|
@ -1457,7 +1458,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||
}
|
||||
src = texD->tex;
|
||||
dxgiFormat = texD->dxgiFormat;
|
||||
pixelSize = u.rb.level() > 0 ? q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize) : texD->m_pixelSize;
|
||||
pixelSize = q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
|
||||
format = texD->m_format;
|
||||
subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(u.rb.layer()), texD->mipLevelCount);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1506,7 +1506,8 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||
trackedImageBarrier(cbD, srcD, QGles2Texture::AccessRead);
|
||||
trackedImageBarrier(cbD, dstD, QGles2Texture::AccessUpdate);
|
||||
|
||||
const QSize size = u.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize();
|
||||
const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
|
||||
const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
|
||||
// do not translate coordinates, even if sp is bottom-left from gl's pov
|
||||
const QPoint sp = u.desc.sourceTopLeft();
|
||||
const QPoint dp = u.desc.destinationTopLeft();
|
||||
|
|
@ -1532,8 +1533,8 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||
cmd.args.copyTex.dstX = dp.x();
|
||||
cmd.args.copyTex.dstY = dp.y();
|
||||
|
||||
cmd.args.copyTex.w = size.width();
|
||||
cmd.args.copyTex.h = size.height();
|
||||
cmd.args.copyTex.w = copySize.width();
|
||||
cmd.args.copyTex.h = copySize.height();
|
||||
|
||||
cbD->commands.append(cmd);
|
||||
} else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
|
||||
|
|
|
|||
|
|
@ -1628,7 +1628,8 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||
QMetalTexture *srcD = QRHI_RES(QMetalTexture, u.src);
|
||||
QMetalTexture *dstD = QRHI_RES(QMetalTexture, u.dst);
|
||||
const QPoint dp = u.desc.destinationTopLeft();
|
||||
const QSize size = u.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize();
|
||||
const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
|
||||
const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
|
||||
const QPoint sp = u.desc.sourceTopLeft();
|
||||
|
||||
ensureBlit();
|
||||
|
|
@ -1636,7 +1637,7 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||
sourceSlice: NSUInteger(u.desc.sourceLayer())
|
||||
sourceLevel: NSUInteger(u.desc.sourceLevel())
|
||||
sourceOrigin: MTLOriginMake(NSUInteger(sp.x()), NSUInteger(sp.y()), 0)
|
||||
sourceSize: MTLSizeMake(NSUInteger(size.width()), NSUInteger(size.height()), 1)
|
||||
sourceSize: MTLSizeMake(NSUInteger(copySize.width()), NSUInteger(copySize.height()), 1)
|
||||
toTexture: dstD->d->tex
|
||||
destinationSlice: NSUInteger(u.desc.destinationLayer())
|
||||
destinationLevel: NSUInteger(u.desc.destinationLevel())
|
||||
|
|
@ -1658,11 +1659,10 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||
qWarning("Multisample texture cannot be read back");
|
||||
continue;
|
||||
}
|
||||
readback.pixelSize = u.rb.level() > 0 ? q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize)
|
||||
: texD->m_pixelSize;
|
||||
readback.pixelSize = q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
|
||||
readback.format = texD->m_format;
|
||||
src = texD->d->tex;
|
||||
srcSize = texD->m_pixelSize;
|
||||
srcSize = readback.pixelSize;
|
||||
texD->lastActiveFrameSlot = currentFrameSlot;
|
||||
} else {
|
||||
Q_ASSERT(currentSwapChain);
|
||||
|
|
|
|||
|
|
@ -2913,9 +2913,10 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
|
|||
region.dstOffset.x = u.desc.destinationTopLeft().x();
|
||||
region.dstOffset.y = u.desc.destinationTopLeft().y();
|
||||
|
||||
const QSize size = u.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize();
|
||||
region.extent.width = uint32_t(size.width());
|
||||
region.extent.height = uint32_t(size.height());
|
||||
const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
|
||||
const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
|
||||
region.extent.width = uint32_t(copySize.width());
|
||||
region.extent.height = uint32_t(copySize.height());
|
||||
region.extent.depth = 1;
|
||||
|
||||
trackedImageBarrier(cbD, srcD, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
|
|
@ -2946,8 +2947,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
|
|||
qWarning("Multisample texture cannot be read back");
|
||||
continue;
|
||||
}
|
||||
readback.pixelSize = u.rb.level() > 0 ? q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize)
|
||||
: texD->m_pixelSize;
|
||||
readback.pixelSize = q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
|
||||
readback.format = texD->m_format;
|
||||
texD->lastActiveFrameSlot = currentFrameSlot;
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue