From 51c22a1f51e2f91289c938be7754f957c9bfa47e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 19 May 2021 19:30:53 +0200 Subject: rhi: Add support for 3D textures Supported on OpenGL (and ES) 3.0+ and everywhere else. Can also be a render target, targeting a single slice at a time. Can be mipmapped, cannot be multisample. Reading back a given slice from a 3D texture is left as a future exercise, for now it is documented to be not supported. Upload is going to be limited to one slice in one upload entry, just like we specify one face or one miplevel for cubemap and mipmapped textures. This also involves some welcome hardening of how texture subresources are described internally: as we no longer can count on a layer index between 0..5 (as is the case with cubemaps), simply arrays with MAX_LAYER==6 are no longer sufficient. Switch to sufficiently dynamic data structures where applicable. On Vulkan rendering to a slice needs Vulkan 1.1 (and 1.1 enabled on the VkInstance). Task-number: QTBUG-89703 Change-Id: Ide6c20124ec9201d94ffc339dd479cd1ece777b0 Reviewed-by: Andy Nichols --- tests/auto/gui/rhi/qrhi/tst_qrhi.cpp | 105 ++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) (limited to 'tests/auto/gui/rhi/qrhi') diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp index bdcbc587fc..11e82215d0 100644 --- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp +++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp @@ -135,6 +135,8 @@ private slots: void textureImportOpenGL(); void renderbufferImportOpenGL_data(); void renderbufferImportOpenGL(); + void threeDimTexture_data(); + void threeDimTexture(); private: void setWindowType(QWindow *window, QRhi::Implementation impl); @@ -169,6 +171,11 @@ void tst_QRhi::initTestCase() #endif #ifdef TST_VK + const QVersionNumber supportedVersion = vulkanInstance.supportedApiVersion(); + if (supportedVersion >= QVersionNumber(1, 2)) + vulkanInstance.setApiVersion(QVersionNumber(1, 2)); + else if (supportedVersion >= QVersionNumber(1, 1)) + vulkanInstance.setApiVersion(QVersionNumber(1, 2)); vulkanInstance.setLayers({ "VK_LAYER_KHRONOS_validation" }); vulkanInstance.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions()); vulkanInstance.create(); @@ -358,7 +365,8 @@ void tst_QRhi::create() QRhi::ReadBackAnyTextureFormat, QRhi::PipelineCacheDataLoadSave, QRhi::ImageDataStride, - QRhi::RenderBufferImport + QRhi::RenderBufferImport, + QRhi::ThreeDimensionalTextures }; for (size_t i = 0; i isFeatureSupported(features[i]); @@ -3817,5 +3825,100 @@ void tst_QRhi::renderbufferImportOpenGL() #endif } +void tst_QRhi::threeDimTexture_data() +{ + rhiTestData(); +} + +void tst_QRhi::threeDimTexture() +{ + QFETCH(QRhi::Implementation, impl); + QFETCH(QRhiInitParams *, initParams); + + QScopedPointer rhi(QRhi::create(impl, initParams)); + if (!rhi) + QSKIP("QRhi could not be created, skipping testing 3D textures"); + + if (!rhi->isFeatureSupported(QRhi::ThreeDimensionalTextures)) + QSKIP("Skipping testing 3D textures because they are reported as unsupported"); + + const int WIDTH = 512; + const int HEIGHT = 256; + const int DEPTH = 128; + + { + QScopedPointer texture(rhi->newTexture(QRhiTexture::RGBA8, WIDTH, HEIGHT, DEPTH)); + QVERIFY(texture->create()); + + QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); + QVERIFY(batch); + + for (int i = 0; i < DEPTH; ++i) { + QImage img(WIDTH, HEIGHT, QImage::Format_RGBA8888); + img.fill(QColor::fromRgb(i * 2, 0, 0)); + QRhiTextureUploadEntry sliceUpload(i, 0, QRhiTextureSubresourceUploadDescription(img)); + batch->uploadTexture(texture.data(), sliceUpload); + } + + QVERIFY(submitResourceUpdates(rhi.data(), batch)); + } + + // mipmaps + { + QScopedPointer texture(rhi->newTexture(QRhiTexture::RGBA8, WIDTH, HEIGHT, DEPTH, + 1, QRhiTexture::MipMapped | QRhiTexture::UsedWithGenerateMips)); + QVERIFY(texture->create()); + + QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); + QVERIFY(batch); + + for (int i = 0; i < DEPTH; ++i) { + QImage img(WIDTH, HEIGHT, QImage::Format_RGBA8888); + img.fill(QColor::fromRgb(i * 2, 0, 0)); + QRhiTextureUploadEntry sliceUpload(i, 0, QRhiTextureSubresourceUploadDescription(img)); + batch->uploadTexture(texture.data(), sliceUpload); + } + + batch->generateMips(texture.data()); + + QVERIFY(submitResourceUpdates(rhi.data(), batch)); + } + + // render target (one slice) + // NB with Vulkan we require Vulkan 1.1 for this to work. + { + const int SLICE = 23; + QScopedPointer texture(rhi->newTexture(QRhiTexture::RGBA8, WIDTH, HEIGHT, DEPTH, + 1, QRhiTexture::RenderTarget)); + QVERIFY(texture->create()); + + QRhiColorAttachment att(texture.data()); + att.setLayer(SLICE); + QRhiTextureRenderTargetDescription rtDesc(att); + QScopedPointer rt(rhi->newTextureRenderTarget(rtDesc)); + QScopedPointer rp(rt->newCompatibleRenderPassDescriptor()); + rt->setRenderPassDescriptor(rp.data()); + QVERIFY(rt->create()); + + QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); + QVERIFY(batch); + + for (int i = 0; i < DEPTH; ++i) { + QImage img(WIDTH, HEIGHT, QImage::Format_RGBA8888); + img.fill(QColor::fromRgb(i * 2, 0, 0)); + QRhiTextureUploadEntry sliceUpload(i, 0, QRhiTextureSubresourceUploadDescription(img)); + batch->uploadTexture(texture.data(), sliceUpload); + } + + QRhiCommandBuffer *cb = nullptr; + QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess); + QVERIFY(cb); + cb->beginPass(rt.data(), Qt::blue, { 1.0f, 0 }, batch); + // slice 23 is now blue + cb->endPass(); + rhi->endOffscreenFrame(); + } +} + #include QTEST_MAIN(tst_QRhi) -- cgit v1.2.3