Commit eb7a7ce1 authored by Laszlo Agocs's avatar Laszlo Agocs

d3d: implement basic image copying

With an example.
parent f386a4fd
......@@ -64,6 +64,8 @@ struct {
QRhiResourceUpdateBatch *initialUpdates = nullptr;
int frameCount = 0;
QImage customImage;
QRhiTexture *newTex = nullptr;
int testStage = 0;
} d;
void Window::customInit()
......@@ -172,6 +174,11 @@ void Window::customRelease()
d.tex->releaseAndDestroy();
d.tex = nullptr;
}
if (d.newTex) {
d.newTex->releaseAndDestroy();
d.newTex = nullptr;
}
}
void Window::customRender()
......@@ -191,20 +198,59 @@ void Window::customRender()
mvp.rotate(d.rotation, 0, 1, 0);
u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
// After some time, partially change the texture.
if (d.frameCount > 100) {
QRhiTextureUploadDescription desc;
QRhiTextureUploadDescription::Layer layer;
QRhiTextureUploadDescription::Layer::MipLevel mipDesc;
mipDesc.image = d.customImage;
// The image here is smaller than the original. Use a non-zero position
// to make it more interesting.
mipDesc.destinationTopLeft = QPointF(100, 20);
layer.mipImages.append(mipDesc);
desc.layers.append(layer);
u->uploadTexture(d.tex, desc);
if (d.frameCount > 0 && (d.frameCount % 100) == 0) {
d.testStage += 1;
qDebug("testStage = %d", d.testStage);
// Partially change the texture.
if (d.testStage == 1) {
QRhiTextureUploadDescription desc;
QRhiTextureUploadDescription::Layer layer;
QRhiTextureUploadDescription::Layer::MipLevel mipDesc;
mipDesc.image = d.customImage;
// The image here is smaller than the original. Use a non-zero position
// to make it more interesting.
mipDesc.destinationTopLeft = QPointF(100, 20);
layer.mipImages.append(mipDesc);
desc.layers.append(layer);
u->uploadTexture(d.tex, desc);
}
// Exercise image copying.
if (d.testStage == 2) {
const QSize sz = d.tex->pixelSize();
d.newTex = m_r->newTexture(QRhiTexture::RGBA8, sz);
d.newTex->build();
QImage empty(sz.width(), sz.height(), QImage::Format_RGBA8888);
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 = QPointF(0, 20);
desc.pixelSize = QSizeF(sz.width() / 2.0f, sz.height() - 20);
desc.destinationTopLeft = QPointF(sz.width() / 2.0f, 20);
u->copyTexture(d.newTex, d.tex, desc);
// Now replace d.tex with d.newTex as the shader resource.
auto bindings = d.srb->bindings();
bindings[1].stex.tex = d.newTex; // see customInit, this was d.tex originally
d.srb->setBindings(bindings);
// "rebuild", whatever that means for a given backend. This srb is
// already live as the ps in the setGraphicsPipeline references it,
// but that's fine. Changes will be picked up automatically.
d.srb->build();
}
// Exercise simple, full texture copy.
if (d.testStage == 5)
u->copyTexture(d.newTex, d.tex);
}
QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
......
......@@ -445,6 +445,16 @@ void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &imag
uploadTexture(tex, {{{{{ image }}}}});
}
void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
{
d->textureCopies.append({ dst, src, desc });
}
void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src)
{
d->textureCopies.append({ dst, src, QRhiTextureCopyDescription() });
}
void QRhiResourceUpdateBatch::prepareTextureForUse(QRhiTexture *tex, TexturePrepareFlags flags)
{
d->texturePrepares.append({ tex, flags });
......@@ -486,6 +496,7 @@ void QRhiResourceUpdateBatchPrivate::free()
dynamicBufferUpdates.clear();
staticBufferUploads.clear();
textureUploads.clear();
textureCopies.clear();
texturePrepares.clear();
rhi->resUpdPoolMap.clearBit(poolIndex);
......@@ -497,6 +508,7 @@ void QRhiResourceUpdateBatchPrivate::merge(QRhiResourceUpdateBatchPrivate *other
dynamicBufferUpdates += other->dynamicBufferUpdates;
staticBufferUploads += other->staticBufferUploads;
textureUploads += other->textureUploads;
textureCopies += other->textureCopies;
texturePrepares += other->texturePrepares;
}
......
......@@ -284,6 +284,21 @@ Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription::Layer::MipLevel, Q_MOVABLE_TYPE
Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription::Layer, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_MOVABLE_TYPE);
struct Q_RHI_EXPORT QRhiTextureCopyDescription
{
QSizeF pixelSize; // empty = entire texture
int sourceLayer = 0;
int sourceLevel = 0;
QPointF sourceTopLeft;
int destinationLayer = 0;
int destinationLevel = 0;
QPointF destinationTopLeft;
};
Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_MOVABLE_TYPE);
struct Q_RHI_EXPORT QRhiReadbackDescription
{
QRhiReadbackDescription() { } // source is the current back buffer (if swapchain supports readback)
......@@ -873,6 +888,8 @@ public:
void uploadStaticBuffer(QRhiBuffer *buf, const void *data);
void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc);
void uploadTexture(QRhiTexture *tex, const QImage &image); // shortcut
void copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc);
void copyTexture(QRhiTexture *dst, QRhiTexture *src); // shortcut
// This is not normally needed, textures that have an upload or are used
// with a TextureRenderTarget will be fine without it. May be more relevant later.
......
......@@ -168,6 +168,17 @@ struct QRhiResourceUpdateBatchPrivate
QRhiTextureUploadDescription desc;
};
struct TextureCopy {
TextureCopy() { }
TextureCopy(QRhiTexture *dst_, QRhiTexture *src_, const QRhiTextureCopyDescription &desc_)
: dst(dst_), src(src_), desc(desc_)
{ }
QRhiTexture *dst = nullptr;
QRhiTexture *src = nullptr;
QRhiTextureCopyDescription desc;
};
struct TexturePrepare {
TexturePrepare() { }
TexturePrepare(QRhiTexture *tex_, QRhiResourceUpdateBatch::TexturePrepareFlags flags_)
......@@ -181,6 +192,7 @@ struct QRhiResourceUpdateBatchPrivate
QVector<DynamicBufferUpdate> dynamicBufferUpdates;
QVector<StaticBufferUpload> staticBufferUploads;
QVector<TextureUpload> textureUploads;
QVector<TextureCopy> textureCopies;
QVector<TexturePrepare> texturePrepares;
QRhiResourceUpdateBatch *q = nullptr;
......@@ -196,6 +208,7 @@ struct QRhiResourceUpdateBatchPrivate
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::StaticBufferUpload, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TextureUpload, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TextureCopy, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TexturePrepare, Q_MOVABLE_TYPE);
template<typename T>
......
......@@ -767,6 +767,27 @@ void QRhiD3D11::commitResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
}
}
for (const QRhiResourceUpdateBatchPrivate::TextureCopy &u : ud->textureCopies) {
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 QSizeF size = u.desc.pixelSize.isEmpty() ? srcD->m_pixelSize : u.desc.pixelSize;
D3D11_BOX srcBox;
srcBox.left = u.desc.sourceTopLeft.x();
srcBox.top = u.desc.sourceTopLeft.y();
srcBox.front = 0;
// back, right, bottom are exclusive
srcBox.right = srcBox.left + size.width();
srcBox.bottom = srcBox.top + size.height();
srcBox.back = 1;
context->CopySubresourceRegion(dstD->tex, dstSubRes, dx, dy, 0,
srcD->tex, srcSubRes, &srcBox);
}
ud->free();
}
......
vk, gl, mtl: texcopy
mtl: tex upload with pos
copyimage (color, with rect?, no resolve or transforms here)
mtl: rhi without a window, offscreen frame
mtl: readback (tex, backbuffer)
gl, mtl: compressed textures
......@@ -55,6 +55,8 @@ dxc for d3d as an alternative to fxc?
hlsl -> dxc -> spirv -> spirv-cross hmmm...
+++ done
d3d: texcopy
copyimage (color, with rect?, no resolve or transforms here)
vk, d3d, gl: tex upload with pos
res upd batch combine
gl: offscreen frame, readback
......
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