Commit 2f13bba5 authored by Laszlo Agocs's avatar Laszlo Agocs

Convert texture copy and readback description classes

parent a665fe00
......@@ -204,14 +204,13 @@ void Window::customRender()
empty.fill(Qt::blue);
u->uploadTexture(d.newTex, empty);
QRhiTextureCopyDescription desc;
// Copy the left-half of tex to the right-half of newTex, while
// leaving the left-half of newTex blue. Keep a 20 pixel gap at
// the top.
desc.sourceTopLeft = QPoint(0, 20);
desc.pixelSize = QSize(sz.width() / 2, sz.height() - 20);
desc.destinationTopLeft = QPoint(sz.width() / 2, 20);
QRhiTextureCopyDescription desc;
desc.setSourceTopLeft(QPoint(0, 20));
desc.setPixelSize(QSize(sz.width() / 2, sz.height() - 20));
desc.setDestinationTopLeft(QPoint(sz.width() / 2, 20));
u->copyTexture(d.newTex, d.tex, desc);
// Now replace d.tex with d.newTex as the shader resource.
......
......@@ -707,11 +707,16 @@ QT_BEGIN_NAMESPACE
\inmodule QtRhi
\brief Describes a texture-to-texture copy operation.
An empty \l pixelSize (the default) indicates that the entire subresource
is to be copied.
An empty pixelSize() indicates that the entire subresource is to be copied.
A default constructed copy description therefore leads to copying the
entire subresource at level 0 of layer 0.
\note The source texture must be created with
QRhiTexture::UsedAsTransferSource.
\note The source and destination rectangles defined by pixelSize(),
sourceTopLeft(), and destinationTopLeft() must fit the source and
destination textures, respectively. The behavior is undefined otherwise.
*/
/*!
......@@ -720,8 +725,8 @@ QT_BEGIN_NAMESPACE
\brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
The source of the readback operation is either a QRhiTexture or the
current backbuffer of the currently targeted QRhiSwapChain. When \l
texture is not set, the swapchain is used. Otherwise the specified
current backbuffer of the currently targeted QRhiSwapChain. When
texture() is not set, the swapchain is used. Otherwise the specified
QRhiTexture is treated as the source.
\note Textures used in readbacks must be created with
......@@ -730,7 +735,7 @@ QT_BEGIN_NAMESPACE
\note Swapchains used in readbacks must be created with
QRhiSwapChain::UsedAsTransferSource.
\l layer and \l level are only applicable when the source is a QRhiTexture.
layer() and level() are only applicable when the source is a QRhiTexture.
\note Multisample textures cannot be read back. Readbacks are supported for
multisample swapchain buffers however.
......
......@@ -427,29 +427,65 @@ private:
Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_MOVABLE_TYPE);
struct Q_RHI_EXPORT QRhiTextureCopyDescription
class Q_RHI_EXPORT QRhiTextureCopyDescription
{
QSize pixelSize;
public:
QRhiTextureCopyDescription() { }
QSize pixelSize() const { return m_pixelSize; }
void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
int sourceLayer() const { return m_sourceLayer; }
void setSourceLayer(int layer) { m_sourceLayer = layer; }
int sourceLevel() const { return m_sourceLevel; }
void setSourceLevel(int level) { m_sourceLevel = level; }
QPoint sourceTopLeft() const { return m_sourceTopLeft; }
void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
int destinationLayer() const { return m_destinationLayer; }
void setDestinationLayer(int layer) { m_destinationLayer = layer; }
int destinationLevel() const { return m_destinationLevel; }
void setDestinationLevel(int level) { m_destinationLevel = level; }
QPoint destinationTopLeft() const { return m_destinationTopLeft; }
void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
private:
QSize m_pixelSize;
int sourceLayer = 0;
int sourceLevel = 0;
QPoint sourceTopLeft;
int m_sourceLayer = 0;
int m_sourceLevel = 0;
QPoint m_sourceTopLeft;
int destinationLayer = 0;
int destinationLevel = 0;
QPoint destinationTopLeft;
int m_destinationLayer = 0;
int m_destinationLevel = 0;
QPoint m_destinationTopLeft;
};
Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_MOVABLE_TYPE);
struct Q_RHI_EXPORT QRhiReadbackDescription
class Q_RHI_EXPORT QRhiReadbackDescription
{
public:
QRhiReadbackDescription() { }
QRhiReadbackDescription(QRhiTexture *texture_) : texture(texture_) { }
QRhiReadbackDescription(QRhiTexture *texture) : m_texture(texture) { }
QRhiTexture *texture = nullptr;
int layer = 0;
int level = 0;
QRhiTexture *texture() const { return m_texture; }
void setTexture(QRhiTexture *tex) { m_texture = tex; }
int layer() const { return m_layer; }
void setLayer(int layer) { m_layer = layer; }
int level() const { return m_level; }
void setLevel(int level) { m_level = level; }
private:
QRhiTexture *m_texture = nullptr;
int m_layer = 0;
int m_level = 0;
};
Q_DECLARE_TYPEINFO(QRhiReadbackDescription, Q_MOVABLE_TYPE);
......
......@@ -1007,14 +1007,14 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
Q_ASSERT(u.src && u.dst);
QD3D11Texture *srcD = QRHI_RES(QD3D11Texture, u.src);
QD3D11Texture *dstD = QRHI_RES(QD3D11Texture, u.dst);
UINT srcSubRes = D3D11CalcSubresource(u.desc.sourceLevel, u.desc.sourceLayer, srcD->mipLevelCount);
UINT dstSubRes = D3D11CalcSubresource(u.desc.destinationLevel, u.desc.destinationLayer, dstD->mipLevelCount);
const float dx = u.desc.destinationTopLeft.x();
const float dy = u.desc.destinationTopLeft.y();
const QSize size = u.desc.pixelSize.isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize;
UINT srcSubRes = D3D11CalcSubresource(u.desc.sourceLevel(), u.desc.sourceLayer(), srcD->mipLevelCount);
UINT dstSubRes = D3D11CalcSubresource(u.desc.destinationLevel(), 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 QPoint sp = u.desc.sourceTopLeft();
D3D11_BOX srcBox;
srcBox.left = u.desc.sourceTopLeft.x();
srcBox.top = u.desc.sourceTopLeft.y();
srcBox.left = sp.x();
srcBox.top = sp.y();
srcBox.front = 0;
// back, right, bottom are exclusive
srcBox.right = srcBox.left + size.width();
......@@ -1024,8 +1024,8 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes;
cmd.args.copySubRes.dst = dstD->tex;
cmd.args.copySubRes.dstSubRes = dstSubRes;
cmd.args.copySubRes.dstX = dx;
cmd.args.copySubRes.dstY = dy;
cmd.args.copySubRes.dstX = dp.x();
cmd.args.copySubRes.dstY = dp.y();
cmd.args.copySubRes.src = srcD->tex;
cmd.args.copySubRes.srcSubRes = srcSubRes;
cmd.args.copySubRes.hasSrcBox = true;
......@@ -1043,7 +1043,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QSize pixelSize;
QRhiTexture::Format format;
UINT subres = 0;
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, u.rb.texture);
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, u.rb.texture());
QD3D11SwapChain *swapChainD = nullptr;
if (texD) {
......@@ -1054,12 +1054,12 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
src = texD->tex;
dxgiFormat = texD->dxgiFormat;
pixelSize = texD->m_pixelSize;
if (u.rb.level > 0) {
pixelSize.setWidth(qFloor(float(qMax(1, pixelSize.width() >> u.rb.level))));
pixelSize.setHeight(qFloor(float(qMax(1, pixelSize.height() >> u.rb.level))));
if (u.rb.level() > 0) {
pixelSize.setWidth(qFloor(float(qMax(1, pixelSize.width() >> u.rb.level()))));
pixelSize.setHeight(qFloor(float(qMax(1, pixelSize.height() >> u.rb.level()))));
}
format = texD->m_format;
subres = D3D11CalcSubresource(u.rb.level, u.rb.layer, texD->mipLevelCount);
subres = D3D11CalcSubresource(u.rb.level(), u.rb.layer(), texD->mipLevelCount);
} else {
Q_ASSERT(contextState.currentSwapChain);
swapChainD = QRHI_RES(QD3D11SwapChain, contextState.currentSwapChain);
......
......@@ -784,13 +784,13 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2Texture *srcD = QRHI_RES(QGles2Texture, u.src);
QGles2Texture *dstD = QRHI_RES(QGles2Texture, u.dst);
const QSize size = u.desc.pixelSize.isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize;
const QSize size = u.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize();
// source offset is bottom-left
const float sx = u.desc.sourceTopLeft.x();
const float sy = srcD->m_pixelSize.height() - (u.desc.sourceTopLeft.y() + size.height() - 1);
const float sx = u.desc.sourceTopLeft().x();
const float sy = srcD->m_pixelSize.height() - (u.desc.sourceTopLeft().y() + size.height() - 1);
// destination offset is top-left
const float dx = u.desc.destinationTopLeft.x();
const float dy = u.desc.destinationTopLeft.y();
const float dx = u.desc.destinationTopLeft().x();
const float dy = u.desc.destinationTopLeft().y();
const GLenum srcFaceTargetBase = srcD->m_flags.testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : srcD->target;
const GLenum dstFaceTargetBase = dstD->m_flags.testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : dstD->target;
......@@ -798,15 +798,15 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2CommandBuffer::Command cmd;
cmd.cmd = QGles2CommandBuffer::Command::CopyTex;
cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + u.desc.sourceLayer;
cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + u.desc.sourceLayer();
cmd.args.copyTex.srcTexture = srcD->texture;
cmd.args.copyTex.srcLevel = u.desc.sourceLevel;
cmd.args.copyTex.srcLevel = u.desc.sourceLevel();
cmd.args.copyTex.srcX = sx;
cmd.args.copyTex.srcY = sy;
cmd.args.copyTex.dst = dstD;
cmd.args.copyTex.dstFaceTarget = dstFaceTargetBase + u.desc.destinationLayer;
cmd.args.copyTex.dstLevel = u.desc.destinationLevel;
cmd.args.copyTex.dstFaceTarget = dstFaceTargetBase + u.desc.destinationLayer();
cmd.args.copyTex.dstLevel = u.desc.destinationLevel();
cmd.args.copyTex.dstX = dx;
cmd.args.copyTex.dstY = dy;
......@@ -820,9 +820,9 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2CommandBuffer::Command cmd;
cmd.cmd = QGles2CommandBuffer::Command::ReadPixels;
cmd.args.readPixels.result = u.result;
cmd.args.readPixels.texture = QRHI_RES(QGles2Texture, u.rb.texture);
cmd.args.readPixels.layer = u.rb.layer;
cmd.args.readPixels.level = u.rb.level;
cmd.args.readPixels.texture = QRHI_RES(QGles2Texture, u.rb.texture());
cmd.args.readPixels.layer = u.rb.layer();
cmd.args.readPixels.level = u.rb.level();
cbD->commands.append(cmd);
}
......
......@@ -1234,22 +1234,20 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
Q_ASSERT(u.src && u.dst);
QMetalTexture *srcD = QRHI_RES(QMetalTexture, u.src);
QMetalTexture *dstD = QRHI_RES(QMetalTexture, u.dst);
const float dx = u.desc.destinationTopLeft.x();
const float dy = u.desc.destinationTopLeft.y();
const QSize size = u.desc.pixelSize.isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize;
const float sx = u.desc.sourceTopLeft.x();
const float sy = u.desc.sourceTopLeft.y();
const QPoint dp = u.desc.destinationTopLeft();
const QSize size = u.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize();
const QPoint sp = u.desc.sourceTopLeft();
ensureBlit();
[blitEnc copyFromTexture: srcD->d->tex
sourceSlice: u.desc.sourceLayer
sourceLevel: u.desc.sourceLevel
sourceOrigin: MTLOriginMake(sx, sy, 0)
sourceSlice: u.desc.sourceLayer()
sourceLevel: u.desc.sourceLevel()
sourceOrigin: MTLOriginMake(sp.x(), sp.y(), 0)
sourceSize: MTLSizeMake(size.width(), size.height(), 1)
toTexture: dstD->d->tex
destinationSlice: u.desc.destinationLayer
destinationLevel: u.desc.destinationLevel
destinationOrigin: MTLOriginMake(dx, dy, 0)];
destinationSlice: u.desc.destinationLayer()
destinationLevel: u.desc.destinationLevel()
destinationOrigin: MTLOriginMake(dp.x(), dp.y(), 0)];
}
for (const QRhiResourceUpdateBatchPrivate::TextureRead &u : ud->textureReadbacks) {
......@@ -1258,7 +1256,7 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
aRb.desc = u.rb;
aRb.result = u.result;
QMetalTexture *texD = QRHI_RES(QMetalTexture, aRb.desc.texture);
QMetalTexture *texD = QRHI_RES(QMetalTexture, u.rb.texture());
QMetalSwapChain *swapChainD = nullptr;
id<MTLTexture> src;
QSize srcSize;
......@@ -1268,9 +1266,9 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
continue;
}
aRb.pixelSize = texD->m_pixelSize;
if (u.rb.level > 0) {
aRb.pixelSize.setWidth(qFloor(float(qMax(1, aRb.pixelSize.width() >> u.rb.level))));
aRb.pixelSize.setHeight(qFloor(float(qMax(1, aRb.pixelSize.height() >> u.rb.level))));
if (u.rb.level() > 0) {
aRb.pixelSize.setWidth(qFloor(float(qMax(1, aRb.pixelSize.width() >> u.rb.level()))));
aRb.pixelSize.setHeight(qFloor(float(qMax(1, aRb.pixelSize.height() >> u.rb.level()))));
}
aRb.format = texD->m_format;
src = texD->d->tex;
......@@ -1297,8 +1295,8 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
ensureBlit();
[blitEnc copyFromTexture: src
sourceSlice: aRb.desc.layer
sourceLevel: aRb.desc.level
sourceSlice: u.rb.layer()
sourceLevel: u.rb.level()
sourceOrigin: MTLOriginMake(0, 0, 0)
sourceSize: MTLSizeMake(srcSize.width(), srcSize.height(), 1)
toBuffer: aRb.buf
......
......@@ -2399,22 +2399,22 @@ void QRhiVulkan::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdat
memset(&region, 0, sizeof(region));
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.srcSubresource.mipLevel = u.desc.sourceLevel;
region.srcSubresource.baseArrayLayer = u.desc.sourceLayer;
region.srcSubresource.mipLevel = u.desc.sourceLevel();
region.srcSubresource.baseArrayLayer = u.desc.sourceLayer();
region.srcSubresource.layerCount = 1;
region.srcOffset.x = u.desc.sourceTopLeft.x();
region.srcOffset.y = u.desc.sourceTopLeft.y();
region.srcOffset.x = u.desc.sourceTopLeft().x();
region.srcOffset.y = u.desc.sourceTopLeft().y();
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.dstSubresource.mipLevel = u.desc.destinationLevel;
region.dstSubresource.baseArrayLayer = u.desc.destinationLayer;
region.dstSubresource.mipLevel = u.desc.destinationLevel();
region.dstSubresource.baseArrayLayer = u.desc.destinationLayer();
region.dstSubresource.layerCount = 1;
region.dstOffset.x = u.desc.destinationTopLeft.x();
region.dstOffset.y = u.desc.destinationTopLeft.y();
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;
const QSize size = u.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize();
region.extent.width = size.width();
region.extent.height = size.height();
region.extent.depth = 1;
......@@ -2437,7 +2437,7 @@ void QRhiVulkan::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdat
aRb.desc = u.rb;
aRb.result = u.result;
QVkTexture *texD = QRHI_RES(QVkTexture, aRb.desc.texture);
QVkTexture *texD = QRHI_RES(QVkTexture, u.rb.texture());
QVkSwapChain *swapChainD = nullptr;
if (texD) {
if (texD->samples > VK_SAMPLE_COUNT_1_BIT) {
......@@ -2445,9 +2445,9 @@ void QRhiVulkan::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdat
continue;
}
aRb.pixelSize = texD->m_pixelSize;
if (u.rb.level > 0) {
aRb.pixelSize.setWidth(qFloor(float(qMax(1, aRb.pixelSize.width() >> u.rb.level))));
aRb.pixelSize.setHeight(qFloor(float(qMax(1, aRb.pixelSize.height() >> u.rb.level))));
if (u.rb.level() > 0) {
aRb.pixelSize.setWidth(qFloor(float(qMax(1, aRb.pixelSize.width() >> u.rb.level()))));
aRb.pixelSize.setHeight(qFloor(float(qMax(1, aRb.pixelSize.height() >> u.rb.level()))));
}
aRb.format = texD->m_format;
} else {
......@@ -2495,8 +2495,8 @@ void QRhiVulkan::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdat
memset(&copyDesc, 0, sizeof(copyDesc));
copyDesc.bufferOffset = 0;
copyDesc.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyDesc.imageSubresource.mipLevel = aRb.desc.level;
copyDesc.imageSubresource.baseArrayLayer = aRb.desc.layer;
copyDesc.imageSubresource.mipLevel = u.rb.level();
copyDesc.imageSubresource.baseArrayLayer = u.rb.layer();
copyDesc.imageSubresource.layerCount = 1;
copyDesc.imageExtent.width = aRb.pixelSize.width();
copyDesc.imageExtent.height = aRb.pixelSize.height();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment