How to cache complex item into texture and release the memory for the actual complex item?

我怕爱的太早我们不能终老 提交于 2019-12-08 06:38:20

问题


I've got a big number of items that are quite complex (memory-heavy), and in order to fit in limited RAM, I want to cache some of them into textures and not keep the actual complex item in memory. In particular, items for which I want to do that are all those (among my complex items) that do not currently need to animate (and this means most of them). For the purposes of this question I call this kind of items "inactive".

My plan was:

  • When an item "foo" becomes inactive:
    • Create dynamically a ShaderEffectSource (with no associated ShaderEffect) with live: false; source: foo, in the same rectangle that was occupied by foo.
    • call scheduleUpdate() on the ShaderEffectSource
    • when the ShaderEffectSource becomes updated, call destroy() on foo

The problem with this plan is with the "when the ShaderEffectSource becomes updated" thing: there is no signal to notify me when that happens. I could use the fact (from the docs) that scheduleUpdate() schedules the update for the next frame. So I would maybe start a Timer that looks something like this:

Timer {
    interval: 1 // 1ms interval meaning "fire every frame"
    property int timesTriggered: 0
    repeat: true
    running: false

    onTriggered: {
        timesTriggered++;
        if(timesTriggered == 2) {
            complexItem.destroy();
            running = false;
        }
    }
}

The == 2 check is to ensure that we've not only reached the next frame (which doesn't guaranteed that the scheduled update has happened already), but we've also reached the frame after that.

But that approach is a hack. Any approach that is not a hack?


回答1:


Sounds like you need to use QQuickRenderControl. I haven't had my time with it yet, but from the doc it sounds like it is exactly what you need:

The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph onto an offscreen render target in a fully application-controlled manner.

QQuickWindow and QQuickView and their associated internal render loops render the Qt Quick scene onto a native window. In some cases, for example when integrating with 3rd party OpenGL renderers, it might be beneficial to get the scene into a texture that can then be used in arbitrary ways by the external rendering engine. QQuickRenderControl makes this possible in a hardware accelerated manner, unlike the performance-wise limited alternative of using QQuickWindow::grabWindow()

When using a QQuickRenderControl, the QQuickWindow does not have to be shown or even created at all..

Management of the context and framebuffer object is up to the application...

There were some ways to achieve something similar prior to the introduction of QQuickRenderControl, but that adds a lot of convenience to the process. The texture don't have to traverse VRAM to RAM to VRAM, and you have full control of its lifetime and such, so you can implement a QQuickItem which basically just draws the texture using the efficient SG API.




回答2:


Maybe you can do it with grabToImage

import QtQuick 2.7
import QtQuick.Controls 2.0

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    id: appWindow
    width: 1024
    height: 800
    visible: true
    Button {
        y: 410
        text: 'run ' + counter
        onClicked: foo()
    }
    property int counter: 0

    function foo() {
        counter++
        gc()
        var c = test.createObject(appWindow)
        c.grabToImage(function(result) {
            if (image.result) {               // <-- Delete what is possible
                image.result.image.destroy()
                image.result.destroy()
            } 
            image.result = result
        }, Qt.size(400, 400))
        c.destroy()
    }

    Image {
        id: image
        width: 400
        height: 400
        x: 100
        property var result
        source: result ? result.url : ''
        onSourceChanged: foo()
    }

    Component {
        id: test
        Grid {
            width: 400
            height: 400
            columns: 40
            rows: 40
            Repeater {
                model: 40 * 40
                delegate: Rectangle {
                    width: 10
                    height: 10
                    color: 'green'  // <--- don't always create a new color
                }
            }
            Component.onCompleted: console.log('Created')
            Component.onDestruction: console.log('Destroyed')
        }
    }
}


来源:https://stackoverflow.com/questions/42698176/how-to-cache-complex-item-into-texture-and-release-the-memory-for-the-actual-com

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!