Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. QRHI Compute Shader

QRHI Compute Shader

Scheduled Pinned Locked Moved Unsolved Game Development
3 Posts 2 Posters 403 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    RSteffen
    wrote on last edited by
    #1

    I managed to run a compute shader too. Here some code for testing!

    #version 450
    
    layout(std430, binding = 0) buffer InputBuffer
    {
        float inputData[];
    };
    
    layout(std430, binding = 1) buffer OutputBuffer
    {
        float outputData[];
    };
    
    void main()
    {
        uint globalIdX = gl_GlobalInvocationID.x;
        uint globalIdY = gl_GlobalInvocationID.y;
        uint globalIdZ = gl_GlobalInvocationID.z;
        uint width = gl_WorkGroupSize.x; // Width of the work group
        uint height = gl_WorkGroupSize.y; // Height of the work group
        uint depth = gl_WorkGroupSize.y; // Height of the work group
        uint globalIdx = globalIdZ * width * height + globalIdY * width + globalIdX; // 1D index
        //uint localIndexX = gl_LocalInvocationID.x;
        //uint localIndexY = gl_LocalInvocationID.y;
        //uint localIndexZ = gl_LocalInvocationID.z;
        //uint localIdx = localIndexZ * width * height + localIndexY * width + localIndexX; // 1D index
        float value = inputData[globalIdx]; // Read from the input buffer
        outputData[globalIdx] = value * value;
    }
    

    And the pipeline code:

    bool ComputeBackend::onSquare(std::vector<float> data)
    {
        #ifndef sptr_
    #define sptr_ std::shared_ptr
        #endif
    
        if (!rhi_) return false;
    
        bool compute_feature = rhi_->isFeatureSupported(QRhi::Compute);
        bool readback_feature = rhi_->isFeatureSupported(QRhi::ReadBackNonUniformBuffer);
        qInfo() << "Compute Supported           : " << compute_feature << Qt::endl;
        qInfo() << "Read Back Storage Supported : " << readback_feature << Qt::endl;
        qInfo() << "Read Back Limit             : " << rhi_->resourceLimit(QRhi::MaxAsyncReadbackFrames) << Qt::endl;
        qInfo() << "MaxThreadGroupsX            : " << rhi_->resourceLimit(QRhi::MaxThreadGroupX) << Qt::endl;
        qInfo() << "MaxThreadGroupsY            : " << rhi_->resourceLimit(QRhi::MaxThreadGroupY) << Qt::endl;
        qInfo() << "MaxThreadGroupsZ            : " << rhi_->resourceLimit(QRhi::MaxThreadGroupZ) << Qt::endl;
        qInfo() << "MaxThreadGroupsperDim       : " << rhi_->resourceLimit(QRhi::MaxThreadGroupsPerDimension) << Qt::endl;
    
        if (!compute_feature || !readback_feature) return false;
    
        int num = data.size();
        // compute the optimal groups
        int wGX = num; //rhi_->resourceLimit(QRhi::MaxThreadGroupX);
        int wGY = 1; //rhi_->resourceLimit(QRhi::MaxThreadGroupX);
        int wGZ = 1;//rhi_->resourceLimit(QRhi::MaxThreadGroupZ);
        // Create QRhi buffers
        auto sbuf = sptr_<QRhiBuffer>(rhi_->newBuffer(QRhiBuffer::Static, QRhiBuffer::StorageBuffer, num * sizeof(float)));
        sbuf->create();
        auto dbuf = sptr_<QRhiBuffer>(rhi_->newBuffer(QRhiBuffer::Static, QRhiBuffer::StorageBuffer, num * sizeof(float)));
        dbuf->create();
        auto srb = sptr_<QRhiShaderResourceBindings>(rhi_->newShaderResourceBindings());
        srb->setBindings(
        {
            QRhiShaderResourceBinding::bufferLoad(0, QRhiShaderResourceBinding::ComputeStage, sbuf.get()),
            QRhiShaderResourceBinding::bufferLoadStore(1, QRhiShaderResourceBinding::ComputeStage, dbuf.get())
        });
        srb->create(); 
        auto pipeline = sptr_<QRhiComputePipeline>(rhi_->newComputePipeline());
        pipeline->setShaderStage({QRhiShaderStage::Compute, *(ResourceManager::getUnmanagedShader(":/sort.comp.qsb"))});
        pipeline->setShaderResourceBindings(srb.get());
        pipeline->create();
        // --- create a off screen frame
        QRhiCommandBuffer *cb;
        rhi_->beginOffscreenFrame(&cb);
        auto resourceUpdateBatch = rhi_->nextResourceUpdateBatch();
        resourceUpdateBatch->uploadStaticBuffer(sbuf.get(), data.data());
        resourceUpdateBatch->uploadStaticBuffer(dbuf.get(), data.data());
        cb->beginComputePass(resourceUpdateBatch);//, QRhiCommandBuffer::ExternalContent);
        cb->setComputePipeline(pipeline.get());
        cb->setShaderResources(srb.get()); // srb can be null in which case the current graphics or compute pipeline's associated QRhiShaderResourceBindings is used
        cb->dispatch(wGX, wGY, wGZ); // Adjust for your data size
        //stat = rhi_->finish();// Waits for any work on the graphics queue (where applicable) to complete, then executes all deferred operations, like completing readbacks and resource releases. Can be called inside and outside of a frame, but not inside a pass. Inside a frame it implies submitting any work on the command buffer.
        resourceUpdateBatch = rhi_->nextResourceUpdateBatch();
        // in openGL only one readback is supported - in Vulkan 2
        QRhiReadbackResult rb_dbuf;
        resourceUpdateBatch->readBackBuffer(dbuf.get(), 0, num * sizeof(float), &rb_dbuf);
        cb->endComputePass(resourceUpdateBatch);
        rhi_->endOffscreenFrame(); // calls a finish
        qInfo() << "ReadBack Dbuf: " << rb_dbuf.data.size() << Qt::endl;
    
        if (rb_dbuf.data.size())
        {
            QByteArray &dba = rb_dbuf.data;
            float *ddata = reinterpret_cast<float *>(dba.data());
            // check the data
    
            for (int i = 0; i < num; ++i)
            {
                if (ddata[i] != (data[i]*data[i]))
                {
                    qInfo() << i - 1 << data[i - 1] << ddata[i - 1] << Qt::endl;
                    qCritical() << i << data[i] << ddata[i] << Qt::endl;
                    break;
                }
            }
        }
        return true;
    }
    

    Please note, that OpenGL only support 1 buffer readback, vulkan support 2 buffer readback. Also setting the MaxThreadGroupsX is crutial.

    Have fun.

    1 Reply Last reply
    0
    • R Offline
      R Offline
      RSteffen
      wrote on last edited by
      #2

      I dont know why, but this code works with vulkan only.

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        I haven't tested QRhi yet but did you try the RHI Window example to see if things are running on all the backends you have on your machine ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved